├── .clang-format ├── .clang-tidy ├── .cmake-format ├── .devcontainer ├── devcontainer.json └── stateless │ └── devcontainer.json ├── .docker ├── .env ├── compose.yaml └── netremote-dev │ ├── 50-sysinfo │ ├── Dockerfile │ ├── build-mac80211_hwsim-kmod.sh │ ├── entrypoint-build.sh │ ├── entrypoint.sh │ └── vcpkg.json ├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── actions │ ├── build-with-docker │ │ └── action.yml │ ├── build-with-host │ │ └── action.yml │ └── build-with-selfhost │ │ └── action.yml ├── pull_request_template.md └── workflows │ ├── build.yml │ └── cicd.yml ├── .gitignore ├── .gitmodules ├── .shellcheckrc ├── .vscode └── extensions.json ├── CMakeLists.txt ├── CMakePresets.json ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── SECURITY.md ├── SUPPORT.md ├── api ├── CMakeLists.txt ├── protocol │ ├── CMakeLists.txt │ └── include │ │ └── microsoft │ │ └── net │ │ └── remote │ │ └── protocol │ │ └── NetRemoteProtocol.hxx └── protos │ ├── NetRemoteDataStream.proto │ ├── NetRemoteDataStreamingService.proto │ ├── NetRemoteNetwork.proto │ ├── NetRemoteRfAttenuator.proto │ ├── NetRemoteRfAttenuatorService.proto │ ├── NetRemoteService.proto │ ├── NetRemoteWifi.proto │ ├── Network8021x.proto │ ├── NetworkCore.proto │ └── WifiCore.proto ├── cmake ├── grpc.cmake ├── protoc.cmake ├── toolchain-config.cmake ├── vcpkg.cmake └── version.cmake ├── config ├── CMakeLists.txt ├── linux │ ├── CMakeLists.txt │ └── network │ │ ├── CMakeLists.txt │ │ ├── cloud │ │ ├── 99-disable-network-config.cfg │ │ └── CMakeLists.txt │ │ └── netplan │ │ ├── 10-network-netremote-all.yaml │ │ └── CMakeLists.txt └── netremote-server-config-schema.json ├── doc ├── docker-run-example.png ├── vscode-dev-container-prompt-select.png ├── vscode-dev-container-prompt-volume.png ├── vscode-dev-container-prompt.png └── vscode-dev-container-setup.gif ├── packaging ├── CMakeLists.txt ├── deb │ ├── CMakeLists.txt │ ├── config-netplan │ │ ├── CMakeLists.txt │ │ └── scripts │ │ │ ├── config │ │ │ ├── confnet │ │ │ ├── confnetplan │ │ │ ├── postinst │ │ │ ├── postrm │ │ │ └── templates │ └── server │ │ ├── CMakeLists.txt │ │ └── scripts │ │ ├── config │ │ ├── confnetdiscovery │ │ ├── postinst │ │ ├── postrm │ │ ├── templates │ │ └── test-config-server-discovery.sh └── vcpkg │ ├── CMakeLists.txt │ ├── GetFileHashSha512.ps1 │ └── ports │ ├── abseil │ ├── 0001-Mark-absl_cc_library-target-as-test-only.patch │ ├── portfile.cmake │ └── vcpkg.json │ └── netremote │ └── portfile.cmake.in ├── scripts └── update-version.sh ├── src ├── CMakeLists.txt ├── common │ ├── CMakeLists.txt │ ├── client │ │ ├── CMakeLists.txt │ │ ├── NetRemoteServerConnection.cxx │ │ ├── Placeholder.cxx │ │ └── include │ │ │ └── microsoft │ │ │ └── net │ │ │ └── remote │ │ │ └── NetRemoteServerConnection.hxx │ ├── dotnet │ │ ├── CMakeLists.txt │ │ ├── NetRemote.sln │ │ ├── NetRemoteClient │ │ │ ├── NetRemoteClient.cs │ │ │ └── NetRemoteClient.csproj │ │ ├── NetRemoteClientUnitTest │ │ │ ├── GlobalUsings.cs │ │ │ ├── NetRemoteClientUnitTest.csproj │ │ │ └── UnitTestNetRemoteClient.cs │ │ └── NetRemoteService │ │ │ ├── NetRemoteService.csproj │ │ │ ├── NetRemoteService.csproj.user │ │ │ ├── Program.cs │ │ │ ├── Properties │ │ │ └── launchSettings.json │ │ │ ├── Services │ │ │ └── NetRemoteService.cs │ │ │ ├── appsettings.Development.json │ │ │ └── appsettings.json │ ├── net │ │ ├── CMakeLists.txt │ │ ├── core │ │ │ ├── CMakeLists.txt │ │ │ └── include │ │ │ │ └── microsoft │ │ │ │ └── net │ │ │ │ ├── INetworkOperations.hxx │ │ │ │ ├── Ieee8021xRadiusAuthentication.hxx │ │ │ │ ├── IpAddressInformation.hxx │ │ │ │ ├── NetworkInterface.hxx │ │ │ │ └── NetworkIpAddress.hxx │ │ ├── network-manager │ │ │ ├── CMakeLists.txt │ │ │ ├── NetworkManager.cxx │ │ │ └── include │ │ │ │ └── microsoft │ │ │ │ └── net │ │ │ │ └── NetworkManager.hxx │ │ ├── service-api │ │ │ ├── CMakeLists.txt │ │ │ └── adapter │ │ │ │ ├── CMakeLists.txt │ │ │ │ ├── ServiceApiNetworkAdapters.cxx │ │ │ │ ├── ServiceApiNetworkDot1xAdapters.cxx │ │ │ │ └── include │ │ │ │ └── microsoft │ │ │ │ └── net │ │ │ │ ├── ServiceApiNetworkAdapters.hxx │ │ │ │ └── ServiceApiNetworkDot1xAdapters.hxx │ │ └── wifi │ │ │ ├── CMakeLists.txt │ │ │ ├── apmanager │ │ │ ├── AccessPointDiscoveryAgent.cxx │ │ │ ├── AccessPointManager.cxx │ │ │ ├── CMakeLists.txt │ │ │ └── include │ │ │ │ └── microsoft │ │ │ │ └── net │ │ │ │ └── wifi │ │ │ │ ├── AccessPointDiscoveryAgent.hxx │ │ │ │ ├── AccessPointManager.hxx │ │ │ │ └── IAccessPointDiscoveryAgentOperations.hxx │ │ │ ├── core │ │ │ ├── AccessPoint.cxx │ │ │ ├── AccessPointAttributes.cxx │ │ │ ├── AccessPointAttributesJsonSerialization.cxx │ │ │ ├── AccessPointController.cxx │ │ │ ├── AccessPointOperationStatus.cxx │ │ │ ├── AccessPointOperationStatusLogOnExit.cxx │ │ │ ├── CMakeLists.txt │ │ │ ├── Ieee80211.cxx │ │ │ ├── Ieee80211AccessPointCapabilities.cxx │ │ │ ├── Ieee80211Authentication.cxx │ │ │ └── include │ │ │ │ └── microsoft │ │ │ │ └── net │ │ │ │ └── wifi │ │ │ │ ├── AccessPoint.hxx │ │ │ │ ├── AccessPointAttributes.hxx │ │ │ │ ├── AccessPointAttributesJsonSerialization.hxx │ │ │ │ ├── AccessPointController.hxx │ │ │ │ ├── AccessPointOperationStatus.hxx │ │ │ │ ├── AccessPointOperationStatusLogOnExit.hxx │ │ │ │ ├── IAccessPoint.hxx │ │ │ │ ├── IAccessPointController.hxx │ │ │ │ ├── Ieee80211.hxx │ │ │ │ ├── Ieee80211AccessPointCapabilities.hxx │ │ │ │ ├── Ieee80211AccessPointConfiguration.hxx │ │ │ │ └── Ieee80211Authentication.hxx │ │ │ └── dot11 │ │ │ ├── CMakeLists.txt │ │ │ └── adapter │ │ │ ├── CMakeLists.txt │ │ │ ├── Ieee80211Dot11Adapters.cxx │ │ │ └── include │ │ │ └── microsoft │ │ │ └── net │ │ │ └── wifi │ │ │ └── Ieee80211Dot11Adapters.hxx │ ├── rfattenuator │ │ ├── CMakeLists.txt │ │ └── include │ │ │ └── microsoft │ │ │ └── net │ │ │ └── remote │ │ │ └── service │ │ │ └── RfAttenuator.hxx │ ├── server │ │ ├── CMakeLists.txt │ │ ├── NetRemoteServer.cxx │ │ ├── NetRemoteServerConfiguration.cxx │ │ ├── NetRemoteServerJsonConfiguration.cxx │ │ ├── config │ │ │ └── netremote-server-config-example.json │ │ └── include │ │ │ └── microsoft │ │ │ └── net │ │ │ └── remote │ │ │ └── service │ │ │ ├── NetRemoteServer.hxx │ │ │ ├── NetRemoteServerConfiguration.hxx │ │ │ └── NetRemoteServerJsonConfiguration.hxx │ ├── service │ │ ├── CMakeLists.txt │ │ ├── NetRemoteApiTrace.cxx │ │ ├── NetRemoteApiTrace.hxx │ │ ├── NetRemoteDataStreamingReactors.cxx │ │ ├── NetRemoteDataStreamingReactors.hxx │ │ ├── NetRemoteDataStreamingService.cxx │ │ ├── NetRemoteDiscoveryService.cxx │ │ ├── NetRemoteRfAttenuatorService.cxx │ │ ├── NetRemoteService.cxx │ │ ├── NetRemoteWifiApiTrace.cxx │ │ ├── NetRemoteWifiApiTrace.hxx │ │ └── include │ │ │ └── microsoft │ │ │ └── net │ │ │ └── remote │ │ │ └── service │ │ │ ├── NetRemoteDataStreamingService.hxx │ │ │ ├── NetRemoteDiscoveryService.hxx │ │ │ ├── NetRemoteRfAttenuatorService.hxx │ │ │ └── NetRemoteService.hxx │ ├── shared │ │ ├── CMakeLists.txt │ │ ├── logging │ │ │ ├── CMakeLists.txt │ │ │ ├── FunctionTracer.cxx │ │ │ ├── LogUtils.cxx │ │ │ └── include │ │ │ │ └── logging │ │ │ │ ├── FunctionTracer.hxx │ │ │ │ └── LogUtils.hxx │ │ ├── notstd │ │ │ ├── CMakeLists.txt │ │ │ └── include │ │ │ │ └── notstd │ │ │ │ ├── Exceptions.hxx │ │ │ │ ├── Memory.hxx │ │ │ │ └── Scope.hxx │ │ └── strings │ │ │ ├── CMakeLists.txt │ │ │ ├── StringHelpers.cxx │ │ │ └── include │ │ │ └── strings │ │ │ ├── StringHelpers.hxx │ │ │ └── StringParsing.hxx │ └── tools │ │ ├── CMakeLists.txt │ │ └── cli │ │ ├── CMakeLists.txt │ │ ├── NetRemoteCli.cxx │ │ ├── NetRemoteCliHandler.cxx │ │ ├── NetRemoteCliHandlerOperations.cxx │ │ └── include │ │ └── microsoft │ │ └── net │ │ └── remote │ │ ├── INetRemoteCliHandlerOperations.hxx │ │ ├── NetRemoteCli.hxx │ │ ├── NetRemoteCliData.hxx │ │ ├── NetRemoteCliHandler.hxx │ │ └── NetRemoteCliHandlerOperations.hxx ├── linux │ ├── CMakeLists.txt │ ├── README.md │ ├── external │ │ ├── CMakeLists.txt │ │ ├── hostap │ │ │ ├── CMakeLists.txt │ │ │ ├── hostapd │ │ │ │ └── .config │ │ │ ├── libwpa_client │ │ │ │ └── .config │ │ │ └── systemd │ │ │ │ ├── CMakeLists.txt │ │ │ │ ├── hostapd-example.conf.in │ │ │ │ ├── hostapd-genconfig@.service.in │ │ │ │ └── hostapd@.service.in │ │ └── libnl │ │ │ └── CMakeLists.txt │ ├── libnl-helpers │ │ ├── CMakeLists.txt │ │ ├── Ieee80211Nl80211Adapters.cxx │ │ ├── Netlink80211.cxx │ │ ├── Netlink80211Interface.cxx │ │ ├── Netlink80211ProtocolState.cxx │ │ ├── Netlink80211Wiphy.cxx │ │ ├── Netlink80211WiphyBand.cxx │ │ ├── Netlink80211WiphyBandFrequency.cxx │ │ ├── NetlinkErrorCategory.cxx │ │ ├── NetlinkException.cxx │ │ ├── NetlinkMessage.cxx │ │ ├── NetlinkRoute.cxx │ │ ├── NetlinkSocket.cxx │ │ └── include │ │ │ └── microsoft │ │ │ └── net │ │ │ └── netlink │ │ │ ├── NetlinkErrorCategory.hxx │ │ │ ├── NetlinkException.hxx │ │ │ ├── NetlinkMessage.hxx │ │ │ ├── NetlinkSocket.hxx │ │ │ ├── nl80211 │ │ │ ├── Ieee80211Nl80211Adapters.hxx │ │ │ ├── Netlink80211.hxx │ │ │ ├── Netlink80211Interface.hxx │ │ │ ├── Netlink80211ProtocolState.hxx │ │ │ ├── Netlink80211Wiphy.hxx │ │ │ ├── Netlink80211WiphyBand.hxx │ │ │ └── Netlink80211WiphyBandFrequency.hxx │ │ │ └── route │ │ │ └── NetlinkRoute.hxx │ ├── net │ │ ├── CMakeLists.txt │ │ ├── core │ │ │ ├── CMakeLists.txt │ │ │ ├── NetworkOperationsLinux.cxx │ │ │ └── include │ │ │ │ └── microsoft │ │ │ │ └── net │ │ │ │ └── NetworkOperationsLinux.hxx │ │ └── wifi │ │ │ ├── CMakeLists.txt │ │ │ ├── apmanager │ │ │ ├── AccessPointDiscoveryAgentOperationsNetlink.cxx │ │ │ ├── CMakeLists.txt │ │ │ └── include │ │ │ │ └── microsoft │ │ │ │ └── net │ │ │ │ └── wifi │ │ │ │ └── AccessPointDiscoveryAgentOperationsNetlink.hxx │ │ │ ├── core │ │ │ ├── AccessPointControllerLinux.cxx │ │ │ ├── AccessPointLinux.cxx │ │ │ ├── CMakeLists.txt │ │ │ ├── Ieee80211WpaAdapters.cxx │ │ │ ├── Ieee80211WpaAdapters.hxx │ │ │ ├── Ieee8021xWpaAdapters.cxx │ │ │ ├── Ieee8021xWpaAdapters.hxx │ │ │ └── include │ │ │ │ └── microsoft │ │ │ │ └── net │ │ │ │ └── wifi │ │ │ │ ├── AccessPointControllerLinux.hxx │ │ │ │ └── AccessPointLinux.hxx │ │ │ └── wpa-controller │ │ │ ├── CMakeLists.txt │ │ │ ├── Hostapd.cxx │ │ │ ├── HostapdException.cxx │ │ │ ├── ProtocolHostapd.cxx │ │ │ ├── ProtocolWpa.cxx │ │ │ ├── WpaCommand.cxx │ │ │ ├── WpaCommandGet.cxx │ │ │ ├── WpaCommandGetConfig.cxx │ │ │ ├── WpaCommandSet.cxx │ │ │ ├── WpaCommandStatus.cxx │ │ │ ├── WpaControlSocket.cxx │ │ │ ├── WpaControlSocketConnection.cxx │ │ │ ├── WpaController.cxx │ │ │ ├── WpaEvent.cxx │ │ │ ├── WpaEventHandler.cxx │ │ │ ├── WpaEventListenerProxy.cxx │ │ │ ├── WpaKeyValuePair.cxx │ │ │ ├── WpaParsingUtilities.cxx │ │ │ ├── WpaParsingUtilities.hxx │ │ │ ├── WpaResponse.cxx │ │ │ ├── WpaResponseParser.cxx │ │ │ └── include │ │ │ └── Wpa │ │ │ ├── Hostapd.hxx │ │ │ ├── IHostapd.hxx │ │ │ ├── IWpaEventListener.hxx │ │ │ ├── ProtocolHostapd.hxx │ │ │ ├── ProtocolWpa.hxx │ │ │ ├── ProtocolWpaConfig.hxx │ │ │ ├── WpaCommand.hxx │ │ │ ├── WpaCommandGet.hxx │ │ │ ├── WpaCommandGetConfig.hxx │ │ │ ├── WpaCommandSet.hxx │ │ │ ├── WpaCommandStatus.hxx │ │ │ ├── WpaControlSocket.hxx │ │ │ ├── WpaControlSocketConnection.hxx │ │ │ ├── WpaController.hxx │ │ │ ├── WpaCore.hxx │ │ │ ├── WpaEvent.hxx │ │ │ ├── WpaEventArgs.hxx │ │ │ ├── WpaEventHandler.hxx │ │ │ ├── WpaEventListenerProxy.hxx │ │ │ ├── WpaKeyValuePair.hxx │ │ │ ├── WpaResponse.hxx │ │ │ ├── WpaResponseGetConfig.hxx │ │ │ ├── WpaResponseParser.hxx │ │ │ └── WpaResponseStatus.hxx │ ├── rfattenuator │ │ ├── CMakeLists.txt │ │ ├── cli │ │ │ ├── CMakeLists.txt │ │ │ └── Main.cxx │ │ └── lib │ │ │ ├── CMakeLists.txt │ │ │ ├── LogHelpers.hxx │ │ │ ├── RfAttenuatorAeroflexWeinschle83XX.cxx │ │ │ ├── RfAttenuatorAeroflexWeinschle83XX.hxx │ │ │ ├── RfAttenuatorExceptionImpl.cxx │ │ │ ├── RfAttenuatorExceptionImpl.hxx │ │ │ ├── RfAttenuatorFactoryImpl.cxx │ │ │ ├── RfAttenuatorImpl.hxx │ │ │ ├── RfAttenuatorProtocol.cxx │ │ │ ├── RfAttenuatorProtocol.hxx │ │ │ ├── RfAttenuatorSoftwareSimulated.cxx │ │ │ ├── RfAttenuatorSoftwareSimulated.hxx │ │ │ ├── RfAttenuatorSubFactory.hxx │ │ │ ├── RfAttenuatorTransport.cxx │ │ │ ├── RfAttenuatorTransport.hxx │ │ │ ├── RfAttenuatorTransportSocketLinux.cxx │ │ │ ├── RfAttenuatorTransportSocketLinux.hxx │ │ │ ├── SocketHelpers.cxx │ │ │ ├── SocketHelpers.hxx │ │ │ └── include │ │ │ └── microsoft │ │ │ └── net │ │ │ └── remote │ │ │ └── service │ │ │ └── RfAttenuatorFactory.hxx │ ├── server │ │ ├── CMakeLists.txt │ │ ├── Main.cxx │ │ ├── NetRemoteDiscoveryServiceLinuxDnssd.cxx │ │ ├── NetRemoteDiscoveryServiceLinuxDnssd.hxx │ │ ├── SystemdResolvedDnssd.cxx │ │ ├── SystemdResolvedDnssd.hxx │ │ └── systemd │ │ │ ├── CMakeLists.txt │ │ │ ├── drop-ins │ │ │ ├── enable-mdns-resolved-global.conf │ │ │ └── enable-mdns.conf │ │ │ └── netremote-server.service.in │ └── tools │ │ ├── CMakeLists.txt │ │ ├── apmonitor │ │ ├── CMakeLists.txt │ │ └── Main.cxx │ │ └── cli │ │ ├── CMakeLists.txt │ │ └── Main.cxx └── windows │ ├── CMakeLists.txt │ ├── README.md │ └── server │ ├── CMakeLists.txt │ └── Main.cxx ├── tests ├── CMakeLists.txt └── unit │ ├── CMakeLists.txt │ ├── Main.cxx │ ├── TestNetRemoteCommon.cxx │ ├── TestNetRemoteCommon.hxx │ ├── TestNetRemoteDataStreamingReactors.cxx │ ├── TestNetRemoteDataStreamingReactors.hxx │ ├── TestNetRemoteDataStreamingServiceClient.cxx │ ├── TestNetRemoteServer.cxx │ ├── TestNetRemoteServiceClient.cxx │ ├── linux │ ├── CMakeLists.txt │ ├── libnl-helpers │ │ ├── CMakeLists.txt │ │ ├── Main.cxx │ │ ├── TestNetlink80211Interface.cxx │ │ ├── TestNetlink80211ProtocolState.cxx │ │ ├── TestNetlinkException.cxx │ │ └── TestNetlinkRoute.cxx │ ├── net │ │ ├── CMakeLists.txt │ │ ├── Main.cxx │ │ └── TestNetworkOperationsLinux.cxx │ ├── rfattenuator │ │ ├── CMakeLists.txt │ │ ├── Main.cxx │ │ └── NetRemoteRfAttenuatorServiceClient.cxx │ └── wifi │ │ ├── CMakeLists.txt │ │ ├── apmanager │ │ ├── CMakeLists.txt │ │ ├── Main.cxx │ │ └── TestAccessPointDiscoveryAgentOperationsNetlink.cxx │ │ ├── core │ │ ├── CMakeLists.txt │ │ ├── TestAccessPointFactoryLinux.cxx │ │ └── TestAccessPointLinux.cxx │ │ ├── helpers │ │ ├── AccessPointFactoryLinuxTest.cxx │ │ ├── CMakeLists.txt │ │ └── include │ │ │ └── microsoft │ │ │ └── net │ │ │ └── wifi │ │ │ └── test │ │ │ └── AccessPointFactoryLinuxTest.hxx │ │ └── wpa-controller │ │ ├── CMakeLists.txt │ │ ├── Main.cxx │ │ ├── README.md │ │ ├── TestHostapd.cxx │ │ ├── TestWpaController.cxx │ │ ├── TestWpaProtocolHostapd.cxx │ │ └── detail │ │ ├── WifiVirtualDeviceManager.cxx │ │ ├── WifiVirtualDeviceManager.hxx │ │ ├── WpaDaemonCatch2EventListener.cxx │ │ ├── WpaDaemonCatch2EventListener.hxx │ │ ├── WpaDaemonInstance.hxx │ │ ├── WpaDaemonManager.cxx │ │ ├── WpaDaemonManager.hxx │ │ └── config │ │ └── HostapdBinaryInfo.hxx.in │ └── net │ ├── CMakeLists.txt │ ├── helpers │ ├── CMakeLists.txt │ ├── NetworkOperationsTest.cxx │ └── include │ │ └── microsoft │ │ └── net │ │ └── test │ │ └── NetworkOperationsTest.hxx │ └── wifi │ ├── CMakeLists.txt │ ├── apmanager │ ├── AccessPointDiscoveryAgentOperationsTest.cxx │ ├── AccessPointDiscoveryAgentOperationsTest.hxx │ ├── CMakeLists.txt │ ├── TestAccessPointDiscoveryAgent.cxx │ └── TestAccessPointManager.cxx │ ├── core │ ├── CMakeLists.txt │ ├── Main.cxx │ ├── TestAccessPoint.cxx │ ├── TestAccessPointAttributes.cxx │ ├── TestAccessPointOperationStatus.cxx │ └── TestIeee80211.cxx │ └── helpers │ ├── AccessPointControllerTest.cxx │ ├── AccessPointManagerTest.cxx │ ├── AccessPointTest.cxx │ ├── CMakeLists.txt │ └── include │ └── microsoft │ └── net │ └── wifi │ └── test │ ├── AccessPointControllerTest.hxx │ ├── AccessPointManagerTest.hxx │ └── AccessPointTest.hxx └── vcpkg.json /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | // For format details, see https://aka.ms/devcontainer.json. For config options, see the 2 | // README at: https://github.com/devcontainers/templates/tree/main/src/docker-existing-docker-compose 3 | { 4 | "name": "NetRemoteDev", 5 | "dockerComposeFile": "../.docker/compose.yaml", 6 | "service": "netremote-dev", 7 | "shutdownAction": "none", 8 | "customizations": { 9 | "vscode": { 10 | "extensions": [ 11 | "EditorConfig.EditorConfig", 12 | "ms-vscode.cmake-tools", 13 | "ms-vscode.cpptools", 14 | "ms-vscode.makefile-tools" 15 | ] 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /.devcontainer/stateless/devcontainer.json: -------------------------------------------------------------------------------- 1 | // For format details, see https://aka.ms/devcontainer.json. For config options, see the 2 | // README at: https://github.com/devcontainers/templates/tree/main/src/docker-existing-docker-compose 3 | { 4 | "name": "NetRemoteDev-Stateless", 5 | "dockerComposeFile": "../../.docker/compose.yaml", 6 | "service": "netremote-dev-stateless", 7 | "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}", 8 | "shutdownAction": "none", 9 | "customizations": { 10 | "vscode": { 11 | "extensions": [ 12 | "EditorConfig.EditorConfig", 13 | "ms-vscode.cmake-tools", 14 | "ms-vscode.cpptools", 15 | "ms-vscode.makefile-tools" 16 | ] 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /.docker/.env: -------------------------------------------------------------------------------- 1 | COMPOSE_CONVERT_WINDOWS_PATHS=1 -------------------------------------------------------------------------------- /.docker/compose.yaml: -------------------------------------------------------------------------------- 1 | 2 | services: 3 | netremote-dev: 4 | build: 5 | context: netremote-dev 6 | target: netremote-dev 7 | tty: true 8 | stdin_open: true 9 | privileged: true 10 | # Enable debugging for ptrace-based debuggers (C++, Go, Rust). 11 | cap_add: 12 | - SYS_PTRACE 13 | security_opt: 14 | - seccomp:unconfined 15 | 16 | netremote-dev-stateless: 17 | extends: netremote-dev 18 | volumes: 19 | - ../..:/workspaces:cached 20 | -------------------------------------------------------------------------------- /.docker/netremote-dev/50-sysinfo: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [ -x /usr/bin/neofetch ]; then 4 | /usr/bin/neofetch 5 | fi 6 | -------------------------------------------------------------------------------- /.docker/netremote-dev/entrypoint-build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euf -o pipefail 4 | 5 | readonly REPOSITORY_ROOT="${1:-${PWD}}" 6 | readonly CMAKE_PRESET_CONFIGURE="${2:-cicd-linux}" 7 | readonly CMAKE_PRESET_BUILD="${3:-build-cicd-linux}" 8 | readonly CMAKE_PRESET_PACKAGE="${4:-cicd-linux}" 9 | readonly CMAKE_PRESET_TEST="${5:-test-cicd-linux}" 10 | readonly CMAKE_BUILD_CONFIG="${6:-Debug}" 11 | 12 | echo "------------------------------------" 13 | echo "Build entrypoint script parameters:" 14 | echo "------------------------------------" 15 | echo "Source Repository Root=${REPOSITORY_ROOT}" 16 | echo "CMake" 17 | echo " Build Configuration=${CMAKE_BUILD_CONFIG}" 18 | echo " Presets" 19 | echo " Configure='${CMAKE_PRESET_CONFIGURE}'" 20 | echo " Build='${CMAKE_PRESET_BUILD}'" 21 | echo " Test='${CMAKE_PRESET_TEST}'" 22 | echo " Package='${CMAKE_PRESET_PACKAGE}'" 23 | 24 | # Verify the repository root is a git repository. 25 | if [[ ! -d ${REPOSITORY_ROOT}/.git ]]; then 26 | echo "Repository root is not a git repository: ${REPOSITORY_ROOT}" 27 | exit 1 28 | fi 29 | 30 | # Verify the vcpkg toolchain file is present. 31 | if [[ ! -f ${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake ]]; then 32 | echo "vcpkg cmake toolchain file not found: ${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" 33 | exit 1 34 | fi 35 | 36 | # Add the workspace directory to the safe directory list. 37 | git config --global --add safe.directory "${REPOSITORY_ROOT}" 38 | 39 | # Change to the root of the repo then execute then perform CMake configure, build, and test. 40 | cd "${REPOSITORY_ROOT}" 41 | cmake --preset "${CMAKE_PRESET_CONFIGURE}" 42 | cmake --build --preset "${CMAKE_PRESET_BUILD}" 43 | ctest --preset "${CMAKE_PRESET_TEST}" -C "${CMAKE_BUILD_CONFIG}" 44 | -------------------------------------------------------------------------------- /.docker/netremote-dev/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euf -o pipefail 4 | 5 | if [ -x /usr/bin/neofetch ]; then 6 | /usr/bin/neofetch 7 | fi 8 | 9 | exec "$@" 10 | -------------------------------------------------------------------------------- /.docker/netremote-dev/vcpkg.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json", 3 | "name": "netremote", 4 | "version-string": "0.4.1", 5 | "dependencies": [ 6 | { 7 | "name": "sdbus-cpp", 8 | "platform": "linux" 9 | }, 10 | { 11 | "name": "libsystemd", 12 | "platform": "linux" 13 | }, 14 | { 15 | "name": "vcpkg-cmake", 16 | "host": true 17 | }, 18 | { 19 | "name": "vcpkg-cmake-config", 20 | "host": true 21 | }, 22 | { 23 | "name": "wil", 24 | "platform": "windows" 25 | }, 26 | "catch2", 27 | "cli11", 28 | "grpc", 29 | "magic-enum", 30 | "plog", 31 | "protobuf" 32 | ], 33 | "overrides": [ 34 | { 35 | "name": "cli11", 36 | "version": "2.3.1" 37 | } 38 | ], 39 | "features": { 40 | "protocol": { 41 | "description": "Enable building the client protocol", 42 | "dependencies": [ 43 | "grpc", 44 | "protobuf" 45 | ] 46 | }, 47 | "server":{ 48 | "description": "Enable building the server", 49 | "dependencies": [ 50 | "netremote" 51 | ] 52 | }, 53 | "tests":{ 54 | "description": "Enable building the tests", 55 | "dependencies": [ 56 | "netremote" 57 | ] 58 | }, 59 | "tools":{ 60 | "description": "Enable building the tools", 61 | "dependencies": [ 62 | "netremote" 63 | ] 64 | } 65 | }, 66 | "default-features": [ 67 | "protocol" 68 | ], 69 | "builtin-baseline": "9224b3bbd8df24999d85720b1d005dd6f969ade0" 70 | } -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @microsoft/net-remote-collaborators -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: 'Bug: ' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **Steps To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Actual behavior** 24 | A clear and concise description of what actually happened. 25 | 26 | **Screenshots** 27 | If applicable, add screenshots to help explain your problem. 28 | 29 | **Version Information** 30 | - Framework version 31 | - Driver version 32 | - OS and version 33 | 34 | **Additional context** 35 | Add any other context about the problem here. -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/actions/build-with-docker/action.yml: -------------------------------------------------------------------------------- 1 | 2 | name: 'Build' 3 | description: 'Build the repository in a docker container' 4 | inputs: 5 | cmake-preset-configure: 6 | required: false 7 | default: 'dev-linux' 8 | description: 'The name of the preset to use for the CMake configure operation' 9 | cmake-preset-build: 10 | required: false 11 | default: 'build-dev-linux' 12 | description: 'The name of the preset to use for the CMake build operation' 13 | cmake-preset-package: 14 | required: false 15 | default: 'packaging-dev-linux' 16 | description: 'The name of the preset to use for the CMake package operation' 17 | cmake-build-config: 18 | required: false 19 | default: 'Debug' 20 | description: 'The build configuration to use for the CMake build operation' 21 | runs: 22 | using: 'docker' 23 | image: 'docker://abeltrano/netremote-build:latest' 24 | args: 25 | - '/github/workspace' 26 | - ${{ inputs.cmake-preset-configure }} 27 | - ${{ inputs.cmake-preset-build }} 28 | - ${{ inputs.cmake-preset-package }} 29 | - ${{ inputs.cmake-build-config }} 30 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | 2 | ### Type 3 | 4 | - [ ] Bug fix 5 | - [ ] Feature addition 6 | - [X] Feature update 7 | - [ ] Documentation 8 | - [ ] Build Infrastructure 9 | 10 | ### Side Effects 11 | 12 | - [ ] Breaking change 13 | - [ ] Non-functional change 14 | 15 | ### Goals 16 | 17 | Describe what the PR intends to achieve. If the change is a new feature, describe what it is. If the change is a bug fix, reference the issue being fixed. Provide any additional context and motivation for making the change. Eg. 18 | > Simplify maintenance of the event loop. A well-known open source library can be used in place of the custom written code, making it easier to use, understand, and debug. 19 | 20 | ### Technical Details 21 | 22 | Describe how the goals of the PR were achieved. Eg. 23 | > Replace custom event loop code with libevent. 24 | 25 | ### Test Results 26 | 27 | Describe which tests were carried out and a summary of their results. Eg. 28 | > Verified Near Object session completed successfully with the following configurations: 29 | > 30 | > - [X] host as controlee 31 | > - [X] host as controller 32 | 33 | ### Reviewer Focus 34 | 35 | Describe what reviewers should focus on. Eg. 36 | 37 | > The event loop could cause the service to exit early if it does not manage object lifetime correctly. Please pay careful attention to how this is achieved in the new event loop. 38 | 39 | ### Future Work 40 | 41 | Describe any future work that is required as a result of this change. Eg. 42 | 43 | > 44 | > - Long-running stress testing needs to be completed. 45 | > - The old event loop code needs to be removed once stress-testing with libevent has been completed. 46 | > 47 | 48 | ### Checklist 49 | 50 | - [ ] Build target `all` compiles cleanly. 51 | - [ ] clang-format and clang-tidy deltas produced no new output. 52 | - [ ] Newly added functions include doxygen-style comment block. 53 | -------------------------------------------------------------------------------- /.github/workflows/cicd.yml: -------------------------------------------------------------------------------- 1 | # Primary workflow that runs on each pull request and push to the primary 2 | # branches, develop and main. 3 | 4 | name: CI/CD 5 | 6 | # Run on workflow dispatch to allow manual triggering of the workflow, and run 7 | # on pushes and PRs to the main branches to enforce code quality and test 8 | # coverage. 9 | on: 10 | push: 11 | branches: 12 | - develop 13 | - main 14 | pull_request: 15 | branches: 16 | - develop 17 | - main 18 | workflow_dispatch: 19 | workflow_call: 20 | 21 | jobs: 22 | build-validation: 23 | name: Build Validation 24 | permissions: 25 | contents: read 26 | actions: read 27 | security-events: write 28 | concurrency: 29 | group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} 30 | cancel-in-progress: true 31 | uses: ./.github/workflows/build.yml 32 | with: 33 | build-types: "[ 'Debug' ]" 34 | test: true 35 | preset-name: 'cicd' 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # VS and VSCode 2 | .vs 3 | .vscode/launch.json 4 | .vscode/settings.json 5 | bin/ 6 | obj/ 7 | 8 | # CMake 9 | build/ 10 | out/ 11 | Testing/ 12 | 13 | # vcpkg 14 | vcpkg_installed*/ 15 | /packaging/vcpkg/ports/netremote/portfile.cmake 16 | 17 | # Debug logs. 18 | *-LogNetRemote*.txt 19 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "vcpkg"] 2 | path = vcpkg 3 | url = https://github.com/microsoft/vcpkg.git 4 | -------------------------------------------------------------------------------- /.shellcheckrc: -------------------------------------------------------------------------------- 1 | 2 | # Allow opening any 'source'd file, even if not specified as input 3 | external-sources=true 4 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "bierner.github-markdown-preview", 4 | "coolbear.systemd-unit-file", 5 | "cschlosser.doxdocgen", 6 | "davidanson.vscode-markdownlint", 7 | "github.copilot-chat", 8 | "github.copilot", 9 | "ms-azuretools.vscode-docker", 10 | "ms-vscode-remote.vscode-remote-extensionpack", 11 | "ms-vscode.cmake-tools", 12 | "ms-vscode.cpptools", 13 | "redhat.vscode-yaml", 14 | "timonwong.shellcheck", 15 | "twxs.cmake", 16 | "vadimcn.vscode-lldb", 17 | "zxh404.vscode-proto3" 18 | ] 19 | } -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Microsoft Open Source Code of Conduct 2 | 3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 4 | 5 | Resources: 6 | 7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) 8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) 9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE 22 | -------------------------------------------------------------------------------- /SUPPORT.md: -------------------------------------------------------------------------------- 1 | 2 | # Support 3 | 4 | ## How to file issues and get help 5 | 6 | This project uses GitHub Issues to track bugs and feature requests. Please search the existing issues before filing new issues to avoid duplicates. For new issues, file your bug or feature request as a new Issue. 7 | 8 | For help and questions about using this project, please contact . 9 | 10 | ## Microsoft Support Policy 11 | 12 | Support for this project is limited to the resources listed above. 13 | -------------------------------------------------------------------------------- /api/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set(PROTO_DIR ${CMAKE_CURRENT_LIST_DIR}/protos) 3 | 4 | # List of all protocol buffer files defining the API. 5 | set(PROTO_FILES 6 | ${PROTO_DIR}/NetRemoteDataStream.proto 7 | ${PROTO_DIR}/NetRemoteDataStreamingService.proto 8 | ${PROTO_DIR}/NetRemoteNetwork.proto 9 | ${PROTO_DIR}/NetRemoteRfAttenuator.proto 10 | ${PROTO_DIR}/NetRemoteRfAttenuatorService.proto 11 | ${PROTO_DIR}/NetRemoteService.proto 12 | ${PROTO_DIR}/NetRemoteWifi.proto 13 | ${PROTO_DIR}/Network8021x.proto 14 | ${PROTO_DIR}/NetworkCore.proto 15 | ${PROTO_DIR}/WifiCore.proto 16 | ) 17 | 18 | # Install the .proto files for consumers that wish to build them themselves. 19 | install( 20 | FILES 21 | ${PROTO_FILES} 22 | DESTINATION "${NETREMOTE_DIR_INSTALL_PUBLIC_HEADER_BASE}/api" 23 | ) 24 | 25 | # Include the API bindings (protocol) if they are not excluded. 26 | if (NOT NETREMOTE_EXCLUDE_API_BINDINGS) 27 | add_subdirectory(protocol) 28 | endif() 29 | -------------------------------------------------------------------------------- /api/protos/NetRemoteDataStream.proto: -------------------------------------------------------------------------------- 1 | 2 | syntax = "proto3"; 3 | 4 | package Microsoft.Net.Remote.DataStream; 5 | 6 | enum DataStreamOperationStatusCode 7 | { 8 | DataStreamOperationStatusCodeUnknown = 0; 9 | DataStreamOperationStatusCodeSucceeded = 1; 10 | DataStreamOperationStatusCodeFailed = 2; 11 | DataStreamOperationStatusCodeCanceled = 3; 12 | DataStreamOperationStatusCodeTimedOut = 4; 13 | } 14 | 15 | message DataStreamOperationStatus 16 | { 17 | DataStreamOperationStatusCode Code = 1; 18 | string Message = 2; 19 | } 20 | 21 | message DataStreamUploadData 22 | { 23 | bytes Data = 1; 24 | } 25 | 26 | message DataStreamDownloadData 27 | { 28 | DataStreamOperationStatus Status = 1; 29 | bytes Data = 2; 30 | uint32 SequenceNumber = 3; 31 | } 32 | 33 | message DataStreamUploadResult 34 | { 35 | DataStreamOperationStatus Status = 1; 36 | uint32 NumberOfDataBlocksReceived = 2; 37 | } 38 | 39 | enum DataStreamType 40 | { 41 | DataStreamTypeUnknown = 0; 42 | DataStreamTypeFixed = 1; 43 | DataStreamTypeContinuous = 2; 44 | } 45 | 46 | enum DataStreamPattern 47 | { 48 | DataStreamPatternUnknown = 0; 49 | DataStreamPatternConstant = 1; 50 | } 51 | 52 | message DataStreamFixedTypeProperties 53 | { 54 | uint32 NumberOfDataBlocksToStream = 1; 55 | } 56 | 57 | message DataStreamContinuousTypeProperties 58 | { 59 | 60 | } 61 | 62 | message DataStreamProperties 63 | { 64 | DataStreamType Type = 1; 65 | DataStreamPattern Pattern = 2; 66 | oneof Properties 67 | { 68 | DataStreamFixedTypeProperties Fixed = 3; 69 | DataStreamContinuousTypeProperties Continuous = 4; 70 | } 71 | } 72 | 73 | message DataStreamDownloadRequest 74 | { 75 | DataStreamProperties Properties = 1; 76 | } 77 | -------------------------------------------------------------------------------- /api/protos/NetRemoteDataStreamingService.proto: -------------------------------------------------------------------------------- 1 | 2 | syntax = "proto3"; 3 | 4 | package Microsoft.Net.Remote.Service; 5 | 6 | import "google/protobuf/empty.proto"; 7 | 8 | import "NetRemoteDataStream.proto"; 9 | 10 | service NetRemoteDataStreaming 11 | { 12 | rpc DataStreamUpload (stream Microsoft.Net.Remote.DataStream.DataStreamUploadData) returns (Microsoft.Net.Remote.DataStream.DataStreamUploadResult); 13 | rpc DataStreamDownload (Microsoft.Net.Remote.DataStream.DataStreamDownloadRequest) returns (stream Microsoft.Net.Remote.DataStream.DataStreamDownloadData); 14 | rpc DataStreamBidirectional (stream Microsoft.Net.Remote.DataStream.DataStreamUploadData) returns (stream Microsoft.Net.Remote.DataStream.DataStreamDownloadData); 15 | rpc DataStreamPing (google.protobuf.Empty) returns (google.protobuf.Empty); 16 | } 17 | -------------------------------------------------------------------------------- /api/protos/NetRemoteNetwork.proto: -------------------------------------------------------------------------------- 1 | 2 | syntax = "proto3"; 3 | 4 | package Microsoft.Net.Remote.Network; 5 | 6 | import "NetworkCore.proto"; 7 | 8 | enum NetworkOperationStatusCode 9 | { 10 | NetworkOperationStatusCodeUnknown = 0; 11 | NetworkOperationStatusCodeSuccess = 1; 12 | NetworkOperationStatusCodeInvalidParameter = 2; 13 | } 14 | 15 | message NetworkOperationStatus 16 | { 17 | NetworkOperationStatusCode Code = 1; 18 | string Message = 2; 19 | } 20 | 21 | message NetworkEnumerateInterfacesRequest 22 | { 23 | } 24 | 25 | message NetworkEnumerateInterfacesResult 26 | { 27 | NetworkOperationStatus Status = 1; 28 | repeated NetworkInterface NetworkInterfaces = 2; 29 | } 30 | -------------------------------------------------------------------------------- /api/protos/NetRemoteRfAttenuator.proto: -------------------------------------------------------------------------------- 1 | 2 | syntax = "proto3"; 3 | 4 | package Microsoft.Net.Remote.RfAttenuator; 5 | 6 | 7 | enum RfAttenuatorOperationStatusCode 8 | { 9 | RfAttenuatorOperationStatusCodeUnknown = 0; 10 | RfAttenuatorOperationStatusCodeSucceeded = 1; 11 | RfAttenuatorOperationStatusCodeFailed = 2; 12 | } 13 | 14 | message RfAttenuatorOperationStatus 15 | { 16 | RfAttenuatorOperationStatusCode Code = 1; 17 | optional string Message = 2; 18 | } 19 | 20 | message ResetResult 21 | { 22 | RfAttenuatorOperationStatus Status = 1; 23 | } 24 | 25 | message GetPropertiesResult 26 | { 27 | RfAttenuatorOperationStatus Status = 1; 28 | repeated uint32 Channels = 2; 29 | double AttenuationRangeDbmMin = 3; 30 | double AttenuationRangeDbmMax = 4; 31 | double AttenuationStepDbmMin = 5; 32 | double AttenuationStepDbmMax = 6; 33 | double AttenuationAccuracyDbmMin = 7; 34 | double AttenuationAccuracyDbmMax = 8; 35 | 36 | uint32 FrequencyBandwidthMHzMin = 9; 37 | uint32 FrequencyBandwidthMHzMax = 10; 38 | 39 | bool SupportsSweep = 11; 40 | 41 | string Identification = 12; 42 | } 43 | 44 | message GetAttenuationRequest 45 | { 46 | uint32 Channel = 1; 47 | } 48 | 49 | message GetAttenuationResult 50 | { 51 | RfAttenuatorOperationStatus Status = 1; 52 | double AttenuationDbm = 2; 53 | } 54 | 55 | message SetAttenuationRequest 56 | { 57 | uint32 Channel = 1; 58 | double AttenuationDbm = 2; 59 | } 60 | message SetAttenuationResult 61 | { 62 | RfAttenuatorOperationStatus Status = 1; 63 | } -------------------------------------------------------------------------------- /api/protos/NetRemoteRfAttenuatorService.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package Microsoft.Net.Remote.Service; 4 | 5 | import "NetRemoteRfAttenuator.proto"; 6 | import "google/protobuf/empty.proto"; 7 | import "google/protobuf/wrappers.proto"; 8 | 9 | service NetRemoteRfAttenuator 10 | { 11 | rpc IsEnabled (google.protobuf.Empty) returns (google.protobuf.BoolValue); 12 | rpc Reset(google.protobuf.Empty) returns (Microsoft.Net.Remote.RfAttenuator.ResetResult); 13 | rpc GetProperties (google.protobuf.Empty) returns (Microsoft.Net.Remote.RfAttenuator.GetPropertiesResult); 14 | rpc GetAttenuationForChannel (Microsoft.Net.Remote.RfAttenuator.GetAttenuationRequest) returns (Microsoft.Net.Remote.RfAttenuator.GetAttenuationResult); 15 | rpc SetAttenuationForChannel (Microsoft.Net.Remote.RfAttenuator.SetAttenuationRequest) returns (Microsoft.Net.Remote.RfAttenuator.SetAttenuationResult); 16 | } 17 | -------------------------------------------------------------------------------- /api/protos/NetRemoteService.proto: -------------------------------------------------------------------------------- 1 | 2 | syntax = "proto3"; 3 | 4 | package Microsoft.Net.Remote.Service; 5 | 6 | import "NetRemoteNetwork.proto"; 7 | import "NetRemoteWifi.proto"; 8 | 9 | service NetRemote 10 | { 11 | // General network related APIs 12 | rpc NetworkInterfacesEnumerate (Microsoft.Net.Remote.Network.NetworkEnumerateInterfacesRequest) returns (Microsoft.Net.Remote.Network.NetworkEnumerateInterfacesResult); 13 | 14 | // Wi-Fi related APIs 15 | rpc WifiAccessPointsEnumerate (Microsoft.Net.Remote.Wifi.WifiAccessPointsEnumerateRequest) returns (Microsoft.Net.Remote.Wifi.WifiAccessPointsEnumerateResult); 16 | rpc WifiAccessPointEnable (Microsoft.Net.Remote.Wifi.WifiAccessPointEnableRequest) returns (Microsoft.Net.Remote.Wifi.WifiAccessPointEnableResult); 17 | rpc WifiAccessPointDisable (Microsoft.Net.Remote.Wifi.WifiAccessPointDisableRequest) returns (Microsoft.Net.Remote.Wifi.WifiAccessPointDisableResult); 18 | rpc WifiAccessPointSetPhyType (Microsoft.Net.Remote.Wifi.WifiAccessPointSetPhyTypeRequest) returns (Microsoft.Net.Remote.Wifi.WifiAccessPointSetPhyTypeResult); 19 | rpc WifiAccessPointSetFrequencyBands (Microsoft.Net.Remote.Wifi.WifiAccessPointSetFrequencyBandsRequest) returns (Microsoft.Net.Remote.Wifi.WifiAccessPointSetFrequencyBandsResult); 20 | rpc WifiAccessPointSetSsid (Microsoft.Net.Remote.Wifi.WifiAccessPointSetSsidRequest) returns (Microsoft.Net.Remote.Wifi.WifiAccessPointSetSsidResult); 21 | rpc WifiAccessPointSetNetworkBridge (Microsoft.Net.Remote.Wifi.WifiAccessPointSetNetworkBridgeRequest) returns (Microsoft.Net.Remote.Wifi.WifiAccessPointSetNetworkBridgeResult); 22 | rpc WifiAccessPointSetAuthenticationDot1x (Microsoft.Net.Remote.Wifi.WifiAccessPointSetAuthenticationDot1xRequest) returns (Microsoft.Net.Remote.Wifi.WifiAccessPointSetAuthenticationDot1xResult); 23 | rpc WifiAccessPointGetAttributes (Microsoft.Net.Remote.Wifi.WifiAccessPointGetAttributesRequest) returns (Microsoft.Net.Remote.Wifi.WifiAccessPointGetAttributesResult); 24 | } 25 | -------------------------------------------------------------------------------- /api/protos/Network8021x.proto: -------------------------------------------------------------------------------- 1 | 2 | syntax = "proto3"; 3 | 4 | package Microsoft.Net; 5 | 6 | enum Dot1xRadiusServerEndpoint 7 | { 8 | Dot1xRadiusServerEndpointUnknown = 0; 9 | Dot1xRadiusServerEndpointAuthentication = 1; 10 | Dot1xRadiusServerEndpointAccounting = 2; 11 | } 12 | 13 | message Dot1xRadiusServerEndpointConfiguration 14 | { 15 | Dot1xRadiusServerEndpoint Endpoint = 1; 16 | string Address = 2; 17 | uint32 Port = 3; 18 | string SharedSecret = 4; 19 | } 20 | 21 | message Dot1xRadiusConfiguration 22 | { 23 | Dot1xRadiusServerEndpointConfiguration AuthenticationServer = 1; 24 | Dot1xRadiusServerEndpointConfiguration AccountingServer = 2; 25 | repeated Dot1xRadiusServerEndpointConfiguration FallbackServers = 3; 26 | } 27 | -------------------------------------------------------------------------------- /api/protos/NetworkCore.proto: -------------------------------------------------------------------------------- 1 | 2 | syntax = "proto3"; 3 | 4 | package Microsoft.Net; 5 | 6 | enum NetworkAddressFamily 7 | { 8 | NetworkAddressFamilyUnknown = 0; 9 | NetworkAddressFamilyIpv4 = 1; 10 | NetworkAddressFamilyIpv6 = 2; 11 | } 12 | 13 | message NetworkAddress 14 | { 15 | NetworkAddressFamily Family = 1; 16 | string Address = 2; 17 | uint32 PrefixLength = 3; 18 | } 19 | 20 | enum NetworkInterfaceKind 21 | { 22 | NetworkInterfaceKindUnknown = 0; 23 | NetworkInterfaceKindOther = 1; 24 | NetworkInterfaceKindEthernet = 2; 25 | NetworkInterfaceKindWifi = 3; 26 | NetworkInterfaceKindBridge = 4; 27 | } 28 | 29 | message NetworkInterface 30 | { 31 | string Id = 1; 32 | NetworkInterfaceKind Kind = 2; 33 | repeated NetworkAddress Addresses = 3; 34 | } 35 | -------------------------------------------------------------------------------- /cmake/grpc.cmake: -------------------------------------------------------------------------------- 1 | 2 | # Find gRPC installation 3 | # Looks for gRPCConfig.cmake file installed by gRPC's cmake installation. 4 | find_package(gRPC CONFIG REQUIRED) 5 | message(STATUS "Using gRPC ${gRPC_VERSION}") 6 | 7 | set(_GRPC_GRPCPP gRPC::grpc++) 8 | if(CMAKE_CROSSCOMPILING) 9 | find_program(_GRPC_CPP_PLUGIN_EXECUTABLE grpc_cpp_plugin) 10 | else() 11 | set(_GRPC_CPP_PLUGIN_EXECUTABLE $) 12 | endif() 13 | -------------------------------------------------------------------------------- /cmake/protoc.cmake: -------------------------------------------------------------------------------- 1 | 2 | # Find Protobuf installation 3 | # Looks for protobuf-config.cmake file installed by Protobuf's cmake installation. 4 | set(protobuf_MODULE_COMPATIBLE TRUE) 5 | find_package(Protobuf CONFIG REQUIRED) 6 | message(STATUS "Using protobuf ${Protobuf_VERSION}") 7 | -------------------------------------------------------------------------------- /cmake/vcpkg.cmake: -------------------------------------------------------------------------------- 1 | 2 | include(CMakeParseArguments) 3 | 4 | # Configures vcpkg for use locally. 5 | # 6 | # This will determine if vcpkg is available. If not, it will clone the vcpkg 7 | # Github repository as a submodule into the directory specified by 8 | # SUBMODULE_ROOT, and instruct cmake to use its toolchain file to help satisfy 9 | # dependencies. It also adds a local git configuration rule to ignore all 10 | # changes in the submodule. 11 | function(vcpkg_configure) 12 | cmake_parse_arguments( 13 | VCPKG 14 | "" 15 | "SUBMODULE_ROOT" 16 | "" 17 | ${ARGN} 18 | ) 19 | 20 | # If the vcpkg root has been specified externally, use it. 21 | if (DEFINED ENV{VCPKG_ROOT}) 22 | set(VCPKG_ROOT "$ENV{VCPKG_ROOT}") 23 | # Otherwise, use the specified submodule root if the toolchain isn't already configured. 24 | elseif ("${VCPKG_CHAINLOAD_TOOLCHAIN_FILE}" STREQUAL "") 25 | set(VCPKG_ROOT ${VCPKG_SUBMODULE_ROOT}) 26 | 27 | find_package(Git REQUIRED) 28 | 29 | # Initialize vcpkg sub-module if not already done. 30 | if (NOT EXISTS ${VCPKG_SUBMODULE_ROOT}/.git) 31 | execute_process(COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive -- ${VCPKG_SUBMODULE_ROOT} 32 | WORKING_DIRECTORY ${VCPKG_SUBMODULE_ROOT}/../ 33 | COMMAND_ERROR_IS_FATAL ANY) 34 | endif() 35 | 36 | # Ignore all changes to the submodule tree. 37 | get_filename_component(VCPKG_SUBMODULE_NAME ${VCPKG_SUBMODULE_ROOT} NAME) 38 | execute_process(COMMAND ${GIT_EXECUTABLE} "config submodule.${VCPKG_SUBMODULE_NAME}.ignore all" 39 | WORKING_DIRECTORY ${VCPKG_SUBMODULE_ROOT}../ 40 | ) 41 | endif() 42 | 43 | # Set the CMake toolchain file to use vcpkg. 44 | if (DEFINED VCPKG_ROOT) 45 | set(CMAKE_TOOLCHAIN_FILE "${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" CACHE FILEPATH "CMake toolchain file") 46 | endif() 47 | 48 | endfunction() 49 | -------------------------------------------------------------------------------- /cmake/version.cmake: -------------------------------------------------------------------------------- 1 | 2 | # Default version values in case we can't get them from git. 3 | set(VERSION_MAJOR 0) 4 | set(VERSION_MINOR 4) 5 | set(VERSION_PATCH 1) 6 | 7 | if (NOT GIT_EXECUTABLE) 8 | message(WARNING "Git not found; falling back to hard-coded version") 9 | else () 10 | message(STATUS "Using git to determine version") 11 | 12 | # Get a list of tags, reverse sorted by tag ref name such that latest tag appears first. 13 | execute_process( 14 | COMMAND "${GIT_EXECUTABLE}" tag -l --sort=-v:refname 15 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} 16 | RESULT_VARIABLE GIT_TAG_RESULT 17 | OUTPUT_VARIABLE GIT_TAG_OUTPUT 18 | OUTPUT_STRIP_TRAILING_WHITESPACE 19 | ) 20 | 21 | # Extract the version from the latest tag. 22 | if (GIT_TAG_RESULT EQUAL 0) 23 | if (GIT_TAG_OUTPUT MATCHES "^v([0-9]+)[.]([0-9]+)[.]([0-9]+)[.]*") 24 | set(VERSION_MAJOR ${CMAKE_MATCH_1}) 25 | set(VERSION_MINOR ${CMAKE_MATCH_2}) 26 | set(VERSION_PATCH ${CMAKE_MATCH_3}) 27 | message(STATUS "Detected version from latest git tag: v${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}") 28 | else() 29 | message(WARNING "Failed to get version from git: ${GIT_TAG_RESULT}; falling back to hard-coded version") 30 | endif() 31 | endif() 32 | endif() 33 | -------------------------------------------------------------------------------- /config/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_subdirectory(linux) 3 | -------------------------------------------------------------------------------- /config/linux/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_subdirectory(network) 3 | -------------------------------------------------------------------------------- /config/linux/network/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_subdirectory(cloud) 3 | add_subdirectory(netplan) 4 | -------------------------------------------------------------------------------- /config/linux/network/cloud/99-disable-network-config.cfg: -------------------------------------------------------------------------------- 1 | network: { config: disabled } -------------------------------------------------------------------------------- /config/linux/network/cloud/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | install( 3 | FILES 4 | ${CMAKE_CURRENT_LIST_DIR}/99-disable-network-config.cfg 5 | DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/cloud/cloud.cfg.d 6 | COMPONENT config-netplan 7 | CONFIGURATIONS Debug 8 | ) 9 | 10 | install( 11 | FILES 12 | ${CMAKE_CURRENT_LIST_DIR}/99-disable-network-config.cfg 13 | DESTINATION /${CMAKE_INSTALL_SYSCONFDIR}/cloud/cloud.cfg.d 14 | COMPONENT config-netplan 15 | CONFIGURATIONS Release RelWithDebInfo MinSizeRel 16 | ) 17 | -------------------------------------------------------------------------------- /config/linux/network/netplan/10-network-netremote-all.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # This plan defines a network topology where a set of interfaces provide gateway services to wireless network clients. 3 | # 4 | # Netplan YAML reference: https://netplan.readthedocs.io/en/stable/netplan-yaml/ 5 | # 6 | # Instructions: 7 | # 1. Identify all interfaces, ethernet or otherwise, that provide network services such as DHCP, DNS, etc. to wireless 8 | # network clients. This will typically be, but is not limited to, a single ethernet interface. 9 | # 2. For each interface identified above: 10 | # a. Add a network interface definition entry according to its type ('ethernets', 'vlans', etc.) which disables all 11 | # IP addressing. See the netplan yaml reference URL above for complete options if necessary. 12 | # b. Add the interface name to the 'interfaces' property of the brgateway0 bridge definition to make the interface 13 | # available to all bridge slaves. 14 | # 3. Re-generate ("render") the plan using 'sudo netplan generate'. 15 | # 4. Optionally validate the generated configuration using 'sudo netplan try'. 16 | # 5. Apply the generated configuration using 'sudo netplan apply'. 17 | # 18 | # The template below describes a plan where a single ethernet network interface 'eno2' provides all gateway services. 19 | # 20 | # network: 21 | # version: 2 22 | # renderer: networkd 23 | # ethernets: 24 | # eno2: # ** Change this to the interface that provides gateway network services (DHCP, DNS, etc.). ** 25 | # # Disable DHCP on all interfaces that will be part of the virtual bridge interface. 26 | # dhcp4: no 27 | # dhcp6: no 28 | # bridges: 29 | # # Define a bridge that will act as a gateway to wireless clients. 30 | # brgateway0: 31 | # # Configure the bridge to obtain its IP address using DHCP. 32 | # dhcp4: yes 33 | # # Include interfaces that provide the gateway services to wireless clients. DO NOT ADD wireless interfaces here. 34 | # interfaces: 35 | # - eno2 36 | -------------------------------------------------------------------------------- /config/linux/network/netplan/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | install( 3 | FILES 4 | ${CMAKE_CURRENT_LIST_DIR}/10-network-netremote-all.yaml 5 | DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/netplan 6 | RENAME 10-network-netremote-all.yaml.template 7 | PERMISSIONS OWNER_READ OWNER_WRITE 8 | COMPONENT config-netplan 9 | CONFIGURATIONS Debug 10 | ) 11 | 12 | install( 13 | FILES 14 | ${CMAKE_CURRENT_LIST_DIR}/10-network-netremote-all.yaml 15 | DESTINATION /${CMAKE_INSTALL_SYSCONFDIR}/netplan 16 | RENAME 10-network-netremote-all.yaml.template 17 | PERMISSIONS OWNER_READ OWNER_WRITE 18 | COMPONENT config-netplan 19 | CONFIGURATIONS Release RelWithDebInfo MinSizeRel 20 | ) 21 | -------------------------------------------------------------------------------- /config/netremote-server-config-schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "$id": "https://github.com/microsoft/netremote/tree/develop/config/netremote-server-config-schema.json", 4 | "$title": "NetRemote Server", 5 | "description": "NetRemote Server Configuration Schema", 6 | "type": "object", 7 | "additionalProperties": false, 8 | "properties": { 9 | "$schema": { 10 | "type": "string", 11 | "description": "The schema version" 12 | }, 13 | "WifiAccessPointAttributes": { 14 | "type": "object", 15 | "description": "Wifi Access Point Attributes", 16 | "additionalProperties": false, 17 | "properties": { 18 | "Properties": { 19 | "type": "object", 20 | "description": "Unstructured (string) Wifi Access Point Properties", 21 | "additionalProperties": { 22 | "type": "object", 23 | "additionalProperties": { 24 | "type": "string", 25 | "description": "Additional properties" 26 | } 27 | } 28 | } 29 | } 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /doc/docker-run-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/netremote/9cc745abb8558f3052452ee3bc07884d09497a08/doc/docker-run-example.png -------------------------------------------------------------------------------- /doc/vscode-dev-container-prompt-select.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/netremote/9cc745abb8558f3052452ee3bc07884d09497a08/doc/vscode-dev-container-prompt-select.png -------------------------------------------------------------------------------- /doc/vscode-dev-container-prompt-volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/netremote/9cc745abb8558f3052452ee3bc07884d09497a08/doc/vscode-dev-container-prompt-volume.png -------------------------------------------------------------------------------- /doc/vscode-dev-container-prompt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/netremote/9cc745abb8558f3052452ee3bc07884d09497a08/doc/vscode-dev-container-prompt.png -------------------------------------------------------------------------------- /doc/vscode-dev-container-setup.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/netremote/9cc745abb8558f3052452ee3bc07884d09497a08/doc/vscode-dev-container-setup.gif -------------------------------------------------------------------------------- /packaging/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | if (NOT NETREMOTE_VCPKG_BUILD_FOR_PORT) 3 | add_subdirectory(vcpkg) 4 | endif() 5 | 6 | if (BUILD_FOR_LINUX) 7 | add_subdirectory(deb) 8 | endif() 9 | -------------------------------------------------------------------------------- /packaging/deb/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | # Uncomment below to debug package generation. 3 | # set(CPACK_DEBIAN_PACKAGE_DEBUG ON) 4 | 5 | # Common CPack configuration for all packages. 6 | set(CPACK_COMPONENTS_GROUPING ONE_PER_GROUP) 7 | set(CPACK_PACKAGE_CONTACT "netremoteowners@microsoft.com") 8 | 9 | # .deb specific configuration. 10 | set(CPACK_GENERATOR "DEB") 11 | set(CPACK_DEB_COMPONENT_INSTALL ON) 12 | set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS YES) 13 | set(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT) 14 | set(CPACK_DEBIAN_DEBUGINFO_PACKAGE ON) 15 | set(CPACK_COMPONENTS_ALL 16 | server 17 | hostapd 18 | dev 19 | config-netplan 20 | ) 21 | 22 | add_subdirectory(config-netplan) 23 | add_subdirectory(server) 24 | 25 | include(CPack) 26 | -------------------------------------------------------------------------------- /packaging/deb/config-netplan/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set(CPACK_DEBIAN_CONFIG-NETPLAN_PACKAGE_CONTROL_EXTRA 3 | "${CMAKE_CURRENT_LIST_DIR}/scripts/config" 4 | "${CMAKE_CURRENT_LIST_DIR}/scripts/confnet" 5 | "${CMAKE_CURRENT_LIST_DIR}/scripts/confnetplan" 6 | "${CMAKE_CURRENT_LIST_DIR}/scripts/postinst" 7 | "${CMAKE_CURRENT_LIST_DIR}/scripts/postrm" 8 | "${CMAKE_CURRENT_LIST_DIR}/scripts/templates" 9 | PARENT_SCOPE 10 | ) 11 | -------------------------------------------------------------------------------- /packaging/deb/config-netplan/scripts/config: -------------------------------------------------------------------------------- 1 | #!/usr/bin/bash 2 | 3 | set -euo pipefail 4 | 5 | # Uncomment the below lines to help debug script execution. 6 | # set -x 7 | # readonly DEBCONF_DEBUG=developer 8 | # export DEBCONF_DEBUG 9 | 10 | # Include helper libraries. 11 | . /usr/share/debconf/confmodule 12 | # shellcheck source=./confnet 13 | . "$(dirname "${0}")"/netremote-config-netplan.confnet 14 | # shellcheck source=./confnetplan 15 | . "$(dirname "${0}")"/netremote-config-netplan.confnetplan 16 | 17 | # Configure the networking stack for use with netremote. 18 | # 19 | # Arguments: 20 | # None 21 | # 22 | function network_stack_configure_interactive() { 23 | debconf_prompt_netplan_configuration 24 | } 25 | 26 | # Main script execution entrypoint. 27 | # 28 | # Arguments: 29 | # Must be those passed to the script (ie. "$@") 30 | # 31 | function main() { 32 | debconf_prompt_network_configure_interactive 33 | 34 | if [[ "${NETWORK_STACK_CONFIGURE}" == "true" ]]; then 35 | network_stack_configure_interactive 36 | fi 37 | } 38 | 39 | main "$@" 40 | -------------------------------------------------------------------------------- /packaging/deb/config-netplan/scripts/confnet: -------------------------------------------------------------------------------- 1 | # shellcheck shell=bash 2 | 3 | # Include debconf shell utility library 4 | . /usr/share/debconf/confmodule 5 | 6 | readonly QUESTION_NETWORK_STACK_CONFIGURATION=netremote/network/configure-interactive 7 | NETWORK_STACK_CONFIGURE= 8 | 9 | # Prompt the user for whether they want to perform interactive network configuration. This stores the user's choice, 10 | # either "true" or "false", in the NETWORK_STACK_CONFIGURE global variable. 11 | # 12 | # Arguments: 13 | # None 14 | function debconf_prompt_network_configure_interactive() { 15 | db_input high "${QUESTION_NETWORK_STACK_CONFIGURATION}" || true 16 | db_go || true 17 | db_get "${QUESTION_NETWORK_STACK_CONFIGURATION}" || true 18 | NETWORK_STACK_CONFIGURE=${RET} 19 | 20 | export NETWORK_STACK_CONFIGURE 21 | } 22 | -------------------------------------------------------------------------------- /packaging/deb/config-netplan/scripts/postinst: -------------------------------------------------------------------------------- 1 | #!/usr/bin/bash 2 | 3 | set -euo pipefail 4 | 5 | # Uncomment the below lines to help debug script execution. 6 | # set -x 7 | # readonly DEBCONF_DEBUG=developer 8 | # export DEBCONF_DEBUG 9 | 10 | # Include helper libraries. 11 | . /usr/share/debconf/confmodule 12 | # shellcheck source=./confnet 13 | . "$(dirname "${0}")"/netremote-config-netplan.confnet 14 | # shellcheck source=./confnetplan 15 | . "$(dirname "${0}")"/netremote-config-netplan.confnetplan 16 | 17 | # Main script execution entrypoint. 18 | # 19 | # Arguments: 20 | # Must be those passed to the script (ie. "$@") 21 | # 22 | function main() { 23 | :; 24 | } 25 | 26 | main "$@" 27 | 28 | -------------------------------------------------------------------------------- /packaging/deb/config-netplan/scripts/postrm: -------------------------------------------------------------------------------- 1 | #!/usr/bin/bash 2 | 3 | set -euo pipefail 4 | 5 | # Uncomment the below lines to help debug script execution. 6 | # set -x 7 | # readonly DEBCONF_DEBUG=developer 8 | # export DEBCONF_DEBUG 9 | 10 | # Include debconf shell utility library 11 | . /usr/share/debconf/confmodule 12 | 13 | # Clear all cached questions/answers. 14 | db_purge 15 | -------------------------------------------------------------------------------- /packaging/deb/server/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set(CPACK_DEBIAN_SERVER_PACKAGE_CONTROL_EXTRA 3 | "${CMAKE_CURRENT_LIST_DIR}/scripts/config" 4 | "${CMAKE_CURRENT_LIST_DIR}/scripts/confnetdiscovery" 5 | "${CMAKE_CURRENT_LIST_DIR}/scripts/postinst" 6 | "${CMAKE_CURRENT_LIST_DIR}/scripts/postrm" 7 | "${CMAKE_CURRENT_LIST_DIR}/scripts/templates" 8 | PARENT_SCOPE 9 | ) 10 | -------------------------------------------------------------------------------- /packaging/deb/server/scripts/config: -------------------------------------------------------------------------------- 1 | #!/usr/bin/bash 2 | 3 | set -euo pipefail 4 | 5 | # Uncomment the below lines to help debug script execution. 6 | # set -x 7 | # readonly DEBCONF_DEBUG=developer 8 | # export DEBCONF_DEBUG 9 | 10 | # Include helper libraries. 11 | . /usr/share/debconf/confmodule 12 | 13 | # shellcheck source=./confnetdiscovery 14 | . "$(dirname "${0}")"/netremote-server.confnetdiscovery 15 | 16 | # Main script execution entrypoint. 17 | # 18 | # Arguments: 19 | # Must be those passed to the script (ie. "$@") 20 | # 21 | function main() { 22 | network_service_discovery_configure_interactive 23 | } 24 | 25 | main "$@" 26 | -------------------------------------------------------------------------------- /packaging/deb/server/scripts/postinst: -------------------------------------------------------------------------------- 1 | #!/usr/bin/bash 2 | 3 | set -euo pipefail 4 | 5 | # Uncomment the below lines to help debug script execution. 6 | # set -x 7 | # readonly DEBCONF_DEBUG=developer 8 | # export DEBCONF_DEBUG 9 | 10 | # Include helper libraries. 11 | . /usr/share/debconf/confmodule 12 | 13 | # Main script execution entrypoint. 14 | # 15 | # Arguments: 16 | # Must be those passed to the script (ie. "$@") 17 | # 18 | function main() { 19 | :; 20 | } 21 | 22 | main "$@" 23 | 24 | -------------------------------------------------------------------------------- /packaging/deb/server/scripts/postrm: -------------------------------------------------------------------------------- 1 | #!/usr/bin/bash 2 | 3 | set -euo pipefail 4 | 5 | # Uncomment the below lines to help debug script execution. 6 | # set -x 7 | # readonly DEBCONF_DEBUG=developer 8 | # export DEBCONF_DEBUG 9 | 10 | # Include debconf shell utility library 11 | . /usr/share/debconf/confmodule 12 | -------------------------------------------------------------------------------- /packaging/deb/server/scripts/templates: -------------------------------------------------------------------------------- 1 | 2 | Template: netremote/network/mdns-configure-interfaces-method 3 | Type: select 4 | Default: Automatic 5 | Choices: Automatic, Manual, Skip 6 | Description: How should multicast DNS (mDNS) be configured? 7 | Multicast DNS (mDNS) is a protocol that allows devices on a local network to discover services running on other devices. mDNS is used by netremote to allow clients to discover netremote servers on the network. Which configuration mode should be used to configure multicast DNS (mDNS)? 8 | . 9 | Automatic: Automatically enable mDNS on all valid interfaces. 10 | Manual: Manually select the interfaces on which to enable mDNS. 11 | Skip: Skip enabling mDNS on any interfaces. 12 | . 13 | If 'Skip' is selected, you must manually enable mDNS on at least one (1) interface for netremote service discovery to work. 14 | 15 | Template: netremote/network/mdns-configure-interfaces-manually 16 | Type: multiselect 17 | Default: ${network-mdns-interfaces-choices} 18 | Choices: ${network-mdns-interfaces-choices} 19 | Description: Select the network interfaces for which multicast DNS (mDNS) will be enabled: 20 | For each network interface selected below, a systemd network drop-in file will be created under /usr/lib/system/network that enables multicast DNS (mDNS). At least one (1) network interface must have mDNS enabled to allow netremote servers to be discovered on the network. 21 | -------------------------------------------------------------------------------- /packaging/deb/server/scripts/test-config-server-discovery.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/bash 2 | 3 | set -euo pipefail 4 | 5 | # Uncomment the below lines to help debug script execution. 6 | set -x 7 | readonly DEBCONF_DEBUG=developer 8 | export DEBCONF_DEBUG 9 | 10 | # Include helper libraries. 11 | . /usr/share/debconf/confmodule 12 | 13 | # shellcheck source=./confnetdiscovery 14 | . confnetdiscovery 15 | 16 | # Main script execution entrypoint. 17 | # 18 | # Arguments: 19 | # Must be those passed to the script (ie. "$@") 20 | # 21 | function main() { 22 | db_x_loadtemplatefile ./templates 23 | network_service_discovery_configure_interactive 24 | } 25 | 26 | main "$@" 27 | -------------------------------------------------------------------------------- /packaging/vcpkg/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | # Define input and output file paths for the vcpkg portfile. 3 | set(VCPKG_PORT_FILE_OUT ${CMAKE_CURRENT_LIST_DIR}/ports/netremote/portfile.cmake) 4 | set(VCPKG_PORT_FILE_IN ${VCPKG_PORT_FILE_OUT}.in) 5 | 6 | # Configure variables to be substituted in the vcpkg portfile. 7 | set(GIT_REF_HEAD main) 8 | set(GIT_REF v${CMAKE_PROJECT_VERSION}) 9 | set(GIT_REF_URL ${CMAKE_PROJECT_HOMEPAGE_URL}/archive/refs/tags/${GIT_REF}.tar.gz) 10 | 11 | # Calculate sha512 hash of the git ref tarball, required for vcpkg portfile. 12 | message(STATUS "Downloading and hashing ${GIT_REF_URL}") 13 | if (BUILD_FOR_LINUX) 14 | execute_process( 15 | COMMAND wget -qO- ${GIT_REF_URL} 16 | COMMAND sha512sum -z 17 | COMMAND bash -c "awk '{ print $1 }'" 18 | COMMAND_ERROR_IS_FATAL ANY 19 | OUTPUT_VARIABLE GIT_REF_SHA512 20 | OUTPUT_STRIP_TRAILING_WHITESPACE 21 | ) 22 | elseif (BUILD_FOR_WINDOWS) 23 | execute_process( 24 | COMMAND powershell ${CMAKE_CURRENT_LIST_DIR}/GetFileHashSha512.ps1 ${GIT_REF_URL} 25 | COMMAND_ERROR_IS_FATAL ANY 26 | OUTPUT_VARIABLE GIT_REF_SHA512 27 | OUTPUT_STRIP_TRAILING_WHITESPACE 28 | ) 29 | endif() 30 | 31 | message(STATUS "${GIT_REF_URL} sha512 hash='${GIT_REF_SHA512}'") 32 | 33 | # Generate portfile.cmake with selected versioning and configuration information. 34 | configure_file(${VCPKG_PORT_FILE_IN} ${VCPKG_PORT_FILE_OUT} @ONLY) 35 | -------------------------------------------------------------------------------- /packaging/vcpkg/GetFileHashSha512.ps1: -------------------------------------------------------------------------------- 1 | 2 | param( 3 | [string]$Uri 4 | ) 5 | 6 | # Download the URI content. 7 | $UriOutFile = Join-Path -Path $Env:TEMP -ChildPath $(Split-Path $Uri -Leaf) 8 | Invoke-WebRequest -Uri $Uri -OutFile $UriOutFile 9 | 10 | # Calculate the SHA512 hash of the downloaded content. 11 | $HashSha512 = Get-FileHash -Path $UriOutFile -Algorithm SHA512 12 | 13 | # Display the hash 14 | $HashSha512 | Select-Object -ExpandProperty Hash 15 | 16 | Remove-Item $UriOutFile 17 | -------------------------------------------------------------------------------- /packaging/vcpkg/ports/abseil/0001-Mark-absl_cc_library-target-as-test-only.patch: -------------------------------------------------------------------------------- 1 | From ccb2f752f6ba4f90eda8931de78c9d8535286602 Mon Sep 17 00:00:00 2001 2 | From: Andrew Beltrano 3 | Date: Tue, 16 Jul 2024 13:36:58 -0600 4 | Subject: [PATCH 1/1] Mark absl_cc_library target as test-only. 5 | 6 | --- 7 | absl/container/CMakeLists.txt | 1 + 8 | 1 file changed, 1 insertion(+) 9 | 10 | diff --git a/absl/container/CMakeLists.txt b/absl/container/CMakeLists.txt 11 | index 128cc0e9..11d65d55 100644 12 | --- a/absl/container/CMakeLists.txt 13 | +++ b/absl/container/CMakeLists.txt 14 | @@ -213,6 +213,7 @@ absl_cc_library( 15 | DEPS 16 | absl::config 17 | GTest::gmock 18 | + TESTONLY 19 | ) 20 | 21 | absl_cc_test( 22 | -- 23 | 2.43.0 24 | 25 | -------------------------------------------------------------------------------- /packaging/vcpkg/ports/abseil/vcpkg.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "abseil", 3 | "version": "20240116.1", 4 | "port-version": 1, 5 | "description": [ 6 | "Abseil is an open-source collection of C++ library code designed to augment the C++ standard library. The Abseil library code is collected from Google's own C++ code base, has been extensively tested and used in production, and is the same code we depend on in our daily coding lives.", 7 | "In some cases, Abseil provides pieces missing from the C++ standard; in others, Abseil provides alternatives to the standard for special needs we've found through usage in the Google code base. We denote those cases clearly within the library code we provide you.", 8 | "Abseil is not meant to be a competitor to the standard library; we've just found that many of these utilities serve a purpose within our code base, and we now want to provide those resources to the C++ community as a whole." 9 | ], 10 | "homepage": "https://github.com/abseil/abseil-cpp", 11 | "license": "Apache-2.0", 12 | "dependencies": [ 13 | { 14 | "name": "vcpkg-cmake", 15 | "host": true 16 | }, 17 | { 18 | "name": "vcpkg-cmake-config", 19 | "host": true 20 | } 21 | ], 22 | "features": { 23 | "cxx17": { 24 | "description": "Enable compiler C++17." 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packaging/vcpkg/ports/netremote/portfile.cmake.in: -------------------------------------------------------------------------------- 1 | 2 | # Note: this file is not used within the project. It exists here for when the vcpkg port for netremote needs to be updated, 3 | # for example, upon new releases, and will automatically be updated with the latest release version/tag. This file along 4 | # with the vcpkg.json file at the root of the project should be copied verbatim to the vcpkg registry or overlay port 5 | # directory being updated with a new version of netremote 6 | 7 | vcpkg_from_github( 8 | OUT_SOURCE_PATH SOURCE_PATH 9 | REPO microsoft/netremote 10 | REF @GIT_REF@ 11 | SHA512 @GIT_REF_SHA512@ 12 | HEAD_REF @GIT_REF_HEAD@ 13 | ) 14 | 15 | vcpkg_find_acquire_program( 16 | GIT 17 | ) 18 | 19 | vcpkg_check_features( 20 | OUT_FEATURE_OPTIONS FEATURE_OPTIONS 21 | INVERTED_FEATURES 22 | api NETREMOTE_EXCLUDE_API 23 | api-bindings NETREMOTE_EXCLUDE_API_BINDINGS 24 | server NETREMOTE_EXCLUDE_SERVER 25 | tests NETREMOTE_EXCLUDE_TESTS 26 | tools NETREMOTE_EXCLUDE_TOOLS 27 | ) 28 | 29 | vcpkg_cmake_configure( 30 | SOURCE_PATH ${SOURCE_PATH} 31 | OPTIONS 32 | -DNETREMOTE_VCPKG_BUILD_FOR_PORT=ON 33 | ${FEATURE_OPTIONS} 34 | ) 35 | 36 | vcpkg_cmake_install() 37 | vcpkg_copy_pdbs() 38 | vcpkg_cmake_config_fixup( 39 | CONFIG_PATH lib/cmake/netremote 40 | ) 41 | 42 | file(REMOVE_RECURSE 43 | "${CURRENT_PACKAGES_DIR}/bin" 44 | "${CURRENT_PACKAGES_DIR}/debug/bin" 45 | "${CURRENT_PACKAGES_DIR}/debug/include" 46 | ) 47 | 48 | file(INSTALL "${SOURCE_PATH}/LICENSE" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}" RENAME copyright) -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_subdirectory(common) 3 | 4 | # Conditional inclusion of OS-dependent source trees. 5 | if (BUILD_FOR_LINUX) 6 | add_subdirectory(linux) 7 | elseif (BUILD_FOR_WINDOWS) 8 | add_subdirectory(windows) 9 | endif() 10 | 11 | # Install the common netremote export 12 | install( 13 | EXPORT ${PROJECT_NAME} 14 | NAMESPACE ${PROJECT_NAME}:: 15 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} 16 | ) 17 | -------------------------------------------------------------------------------- /src/common/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_subdirectory(client) 3 | add_subdirectory(dotnet) 4 | add_subdirectory(net) 5 | add_subdirectory(rfattenuator) 6 | add_subdirectory(server) 7 | add_subdirectory(service) 8 | add_subdirectory(shared) 9 | add_subdirectory(tools) 10 | -------------------------------------------------------------------------------- /src/common/client/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_library(${PROJECT_NAME}-client STATIC "") 3 | 4 | set(NETREMOTE_CLIENT_PUBLIC_INCLUDE ${CMAKE_CURRENT_LIST_DIR}/include) 5 | set(NETREMOTE_CLIENT_PUBLIC_INCLUDE_SUFFIX microsoft/net/remote) 6 | set(NETREMOTE_CLIENT_PUBLIC_INCLUDE_PREFIX ${NETREMOTE_CLIENT_PUBLIC_INCLUDE}/${NETREMOTE_CLIENT_PUBLIC_INCLUDE_SUFFIX}) 7 | 8 | target_sources(${PROJECT_NAME}-client 9 | PRIVATE 10 | NetRemoteServerConnection.cxx 11 | PUBLIC 12 | FILE_SET HEADERS 13 | BASE_DIRS ${NETREMOTE_CLIENT_PUBLIC_INCLUDE} 14 | FILES 15 | ${NETREMOTE_CLIENT_PUBLIC_INCLUDE_PREFIX}/NetRemoteServerConnection.hxx 16 | ) 17 | 18 | target_link_libraries(${PROJECT_NAME}-client 19 | PRIVATE 20 | plog::plog 21 | PUBLIC 22 | ${PROJECT_NAME}-protocol 23 | ) 24 | 25 | install( 26 | TARGETS ${PROJECT_NAME}-client 27 | EXPORT ${PROJECT_NAME} 28 | COMPONENT dev 29 | FILE_SET HEADERS 30 | PUBLIC_HEADER DESTINATION "${NETREMOTE_DIR_INSTALL_PUBLIC_HEADER_BASE}/${NETREMOTE_CLIENT_PUBLIC_INCLUDE_SUFFIX}" 31 | ) 32 | -------------------------------------------------------------------------------- /src/common/client/NetRemoteServerConnection.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | using namespace Microsoft::Net::Remote; 15 | 16 | using namespace Microsoft::Net::Remote::Service; 17 | using namespace Microsoft::Net::Remote::Wifi; 18 | 19 | NetRemoteServerConnection::NetRemoteServerConnection(std::string_view address, std::shared_ptr channel, std::unique_ptr client) : 20 | Address(address), 21 | Channel(std::move(channel)), 22 | Client(std::move(client)) 23 | { 24 | } 25 | 26 | /* static */ 27 | std::shared_ptr 28 | NetRemoteServerConnection::TryEstablishConnection(std::string_view address) 29 | { 30 | // Attempt to establish a connection (channel) to the server. 31 | static constexpr auto DontTryToConnect{ false }; 32 | auto channel = grpc::CreateChannel(std::data(address), grpc::InsecureChannelCredentials()); 33 | if (channel == nullptr || channel->GetState(DontTryToConnect) != GRPC_CHANNEL_IDLE) { 34 | LOGE << "Failed to establish connection channel"; 35 | return nullptr; 36 | } 37 | 38 | // Attempt to create a new client API stub. 39 | auto client = NetRemote::NewStub(channel); 40 | if (client == nullptr) { 41 | LOGE << "Failed to create NetRemote API stub"; 42 | return nullptr; 43 | } 44 | 45 | // Return a new connection object. 46 | auto netRemoteServerConnection = std::make_shared(address, channel, std::move(client)); 47 | return netRemoteServerConnection; 48 | } 49 | -------------------------------------------------------------------------------- /src/common/client/Placeholder.cxx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/netremote/9cc745abb8558f3052452ee3bc07884d09497a08/src/common/client/Placeholder.cxx -------------------------------------------------------------------------------- /src/common/client/include/microsoft/net/remote/NetRemoteServerConnection.hxx: -------------------------------------------------------------------------------- 1 | 2 | #ifndef NET_REMOTE_SERVER_CONNECTION 3 | #define NET_REMOTE_SERVER_CONNECTION 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | namespace Microsoft::Net::Remote 13 | { 14 | /** 15 | * @brief Helper structure to collect server connection information. 16 | */ 17 | struct NetRemoteServerConnection 18 | { 19 | std::string Address; 20 | std::shared_ptr Channel; 21 | std::unique_ptr Client; 22 | 23 | /** 24 | * @brief Construct a new NetRemoteServerConnection object with the specified address, channel, and client. 25 | * 26 | * @param address The address that was used to connect. 27 | * @param channel The established channel. 28 | * @param client The client stub that was obtained from 'channel'. 29 | */ 30 | NetRemoteServerConnection(std::string_view address, std::shared_ptr channel, std::unique_ptr client); 31 | 32 | /** 33 | * @brief Attempt to establish a basic connection to a remote server. 34 | * 35 | * @param address The address to use to connect. Must be in the form :. 36 | * @return std::shared_ptr 37 | */ 38 | static std::shared_ptr 39 | TryEstablishConnection(std::string_view address); 40 | 41 | NetRemoteServerConnection(const NetRemoteServerConnection& other) = delete; 42 | NetRemoteServerConnection(NetRemoteServerConnection&& other) = default; 43 | 44 | NetRemoteServerConnection 45 | operator=(const NetRemoteServerConnection& other) = delete; 46 | 47 | NetRemoteServerConnection& 48 | operator=(NetRemoteServerConnection&& other) = default; 49 | }; 50 | } // namespace Microsoft::Net::Remote 51 | 52 | #endif // NET_REMOTE_SERVER_CONNECTION 53 | -------------------------------------------------------------------------------- /src/common/dotnet/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | include_external_msproject(${PROJECT_NAME}-dotnet 3 | ${CMAKE_CURRENT_LIST_DIR}/NetRemote.sln 4 | ) 5 | -------------------------------------------------------------------------------- /src/common/dotnet/NetRemoteClient/NetRemoteClient.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace Microsoft.Net.Remote.Client 3 | { 4 | public class NetRemoteClient 5 | { 6 | 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/common/dotnet/NetRemoteClientUnitTest/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | global using Microsoft.VisualStudio.TestTools.UnitTesting; -------------------------------------------------------------------------------- /src/common/dotnet/NetRemoteClientUnitTest/NetRemoteClientUnitTest.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net7.0 5 | enable 6 | enable 7 | 8 | false 9 | true 10 | AnyCPU;x64;ARM64;ARM32;x86 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/common/dotnet/NetRemoteClientUnitTest/UnitTestNetRemoteClient.cs: -------------------------------------------------------------------------------- 1 | 2 | using Grpc.Net.Client; 3 | using Microsoft.Net.Remote.Wifi; 4 | using Microsoft.Net.Remote.Service; 5 | 6 | namespace Microsoft.Net.Remote.Client.Test 7 | { 8 | [TestClass] 9 | public class UnitTestNetRemoteClient 10 | { 11 | private static readonly string AddressHttp = "http://localhost:5047"; 12 | private static readonly string AddressHttps = "https://localhost:7073"; 13 | 14 | internal enum ConnectionType 15 | { 16 | Http, 17 | Https, 18 | } 19 | 20 | internal static string ConnectionAddress(ConnectionType connectionType) => connectionType switch 21 | { 22 | ConnectionType.Http => AddressHttp, 23 | ConnectionType.Https => AddressHttps, 24 | _ => throw new NotImplementedException(), 25 | }; 26 | 27 | internal readonly record struct GrpcConnection(GrpcChannel Channel, NetRemote.NetRemoteClient Client); 28 | 29 | internal static GrpcConnection CreateConnection(ConnectionType connectionType) 30 | { 31 | var address = ConnectionAddress(connectionType); 32 | var channel = GrpcChannel.ForAddress(address); 33 | var client = new NetRemote.NetRemoteClient(channel); 34 | 35 | return new GrpcConnection(channel, client); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/common/dotnet/NetRemoteService/NetRemoteService.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net7.0 5 | enable 6 | enable 7 | AnyCPU;x64;ARM64;ARM32;x86 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | Protos\NetRemoteDataStream.proto 21 | 22 | 23 | Protos\NetRemoteDataStreamingService.proto 24 | 25 | 26 | Protos\NetRemoteNetwork.proto 27 | 28 | 29 | Protos\NetRemoteService.proto 30 | 31 | 32 | Protos\NetRemoteWifi.proto 33 | 34 | 35 | Protos\Network8021x.proto 36 | 37 | 38 | Protos\NetworkCore.proto 39 | 40 | 41 | Protos\WifiCore.proto 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /src/common/dotnet/NetRemoteService/NetRemoteService.csproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | http 5 | 6 | 7 | ProjectDebugger 8 | 9 | -------------------------------------------------------------------------------- /src/common/dotnet/NetRemoteService/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Net.Remote.Service; 2 | 3 | var builder = WebApplication.CreateBuilder(args); 4 | 5 | // Add services to the container. 6 | builder.Services.AddGrpc(); 7 | 8 | var app = builder.Build(); 9 | 10 | // Configure the HTTP request pipeline. 11 | app.MapGrpcService(); 12 | app.MapGet("/", () => "Communication with gRPC endpoints must be made through a gRPC client. To learn how to create a client, visit: https://go.microsoft.com/fwlink/?linkid=2086909"); 13 | 14 | app.Run(); 15 | -------------------------------------------------------------------------------- /src/common/dotnet/NetRemoteService/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "http": { 4 | "commandName": "Project", 5 | "dotnetRunMessages": true, 6 | "launchBrowser": false, 7 | "applicationUrl": "http://localhost:5047", 8 | "environmentVariables": { 9 | "ASPNETCORE_ENVIRONMENT": "Development" 10 | } 11 | }, 12 | "https": { 13 | "commandName": "Project", 14 | "dotnetRunMessages": true, 15 | "launchBrowser": false, 16 | "applicationUrl": "https://localhost:7073;http://localhost:5047", 17 | "environmentVariables": { 18 | "ASPNETCORE_ENVIRONMENT": "Development" 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/common/dotnet/NetRemoteService/Services/NetRemoteService.cs: -------------------------------------------------------------------------------- 1 |  2 | using Grpc = global::Grpc.Core; 3 | 4 | namespace Microsoft.Net.Remote.Service 5 | { 6 | public class NetRemoteService : NetRemote.NetRemoteBase 7 | { 8 | private readonly ILogger _logger; 9 | 10 | public NetRemoteService(ILogger logger) 11 | { 12 | _logger = logger; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/common/dotnet/NetRemoteService/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/common/dotnet/NetRemoteService/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*", 9 | "Kestrel": { 10 | "EndpointDefaults": { 11 | "Protocols": "Http2" 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/common/net/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_subdirectory(core) 3 | add_subdirectory(network-manager) 4 | add_subdirectory(service-api) 5 | add_subdirectory(wifi) 6 | -------------------------------------------------------------------------------- /src/common/net/core/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_library(${PROJECT_NAME}-net INTERFACE "") 3 | 4 | set(NET_REMOTE_NET_PUBLIC_INCLUDE ${CMAKE_CURRENT_LIST_DIR}/include) 5 | set(NET_REMOTE_NET_PUBLIC_INCLUDE_SUFFIX microsoft/net) 6 | set(NET_REMOTE_NET_PUBLIC_INCLUDE_PREFIX ${NET_REMOTE_NET_PUBLIC_INCLUDE}/${NET_REMOTE_NET_PUBLIC_INCLUDE_SUFFIX}) 7 | 8 | target_sources(${PROJECT_NAME}-net 9 | PUBLIC 10 | FILE_SET HEADERS 11 | BASE_DIRS ${NET_REMOTE_NET_PUBLIC_INCLUDE} 12 | FILES 13 | ${NET_REMOTE_NET_PUBLIC_INCLUDE_PREFIX}/Ieee8021xRadiusAuthentication.hxx 14 | ${NET_REMOTE_NET_PUBLIC_INCLUDE_PREFIX}/INetworkOperations.hxx 15 | ${NET_REMOTE_NET_PUBLIC_INCLUDE_PREFIX}/IpAddressInformation.hxx 16 | ${NET_REMOTE_NET_PUBLIC_INCLUDE_PREFIX}/NetworkInterface.hxx 17 | ${NET_REMOTE_NET_PUBLIC_INCLUDE_PREFIX}/NetworkIpAddress.hxx 18 | ) 19 | 20 | install( 21 | TARGETS ${PROJECT_NAME}-net 22 | EXPORT ${PROJECT_NAME} 23 | COMPONENT dev 24 | FILE_SET HEADERS 25 | PUBLIC_HEADER DESTINATION "${NETREMOTE_DIR_INSTALL_PUBLIC_HEADER_BASE}/${NET_REMOTE_NET_PUBLIC_INCLUDE_SUFFIX}" 26 | ) 27 | -------------------------------------------------------------------------------- /src/common/net/core/include/microsoft/net/IpAddressInformation.hxx: -------------------------------------------------------------------------------- 1 | 2 | #ifndef IP_ADDRESS_INFORMATION_HXX 3 | #define IP_ADDRESS_INFORMATION_HXX 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | namespace Microsoft::Net 12 | { 13 | /** 14 | * @brief Information about an IP address needed by the server. 15 | */ 16 | struct IpAddressInformation 17 | { 18 | NetworkIpFamily Family{ NetworkIpFamily::Unknown }; 19 | NetworkInterfaceType InterfaceType{ NetworkInterfaceType::Unknown }; 20 | std::string InterfaceName; 21 | 22 | auto 23 | operator<=>(const IpAddressInformation&) const = default; 24 | }; 25 | } // namespace Microsoft::Net 26 | 27 | namespace std 28 | { 29 | template <> 30 | struct hash 31 | { 32 | std::size_t 33 | operator()(const Microsoft::Net::IpAddressInformation& ipInfo) const noexcept 34 | { 35 | return std::hash{}(static_cast(ipInfo.Family)) ^ std::hash{}(static_cast(ipInfo.InterfaceType)); 36 | } 37 | }; 38 | } // namespace std 39 | 40 | #endif // IP_ADDRESS_INFORMATION_HXX 41 | -------------------------------------------------------------------------------- /src/common/net/core/include/microsoft/net/NetworkInterface.hxx: -------------------------------------------------------------------------------- 1 | 2 | #ifndef NETWORK_INTERFACE_HXX 3 | #define NETWORK_INTERFACE_HXX 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | namespace Microsoft::Net 11 | { 12 | /** 13 | * @brief The type of network interface. 14 | */ 15 | enum class NetworkInterfaceType { 16 | Unknown, 17 | Other, 18 | Ethernet, 19 | Wifi, 20 | Bridge, 21 | }; 22 | 23 | /** 24 | * @brief Describes a network interface identifier. 25 | */ 26 | struct NetworkInterfaceId 27 | { 28 | std::string Name; 29 | NetworkInterfaceType Type{ NetworkInterfaceType::Unknown }; 30 | 31 | auto 32 | operator<=>(const NetworkInterfaceId&) const = default; 33 | }; 34 | } // namespace Microsoft::Net 35 | 36 | namespace std 37 | { 38 | template <> 39 | struct hash 40 | { 41 | std::size_t 42 | operator()(const Microsoft::Net::NetworkInterfaceId& networkInterfaceId) const noexcept 43 | { 44 | return std::hash{}(networkInterfaceId.Name); 45 | } 46 | }; 47 | } // namespace std 48 | 49 | #endif // NETWORK_INTERFACE_HXX 50 | -------------------------------------------------------------------------------- /src/common/net/network-manager/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_library(${PROJECT_NAME}-network-manager STATIC "") 3 | 4 | set(NET_REMOTE_NETWORK_MANAGER_PUBLIC_INCLUDE ${CMAKE_CURRENT_LIST_DIR}/include) 5 | set(NET_REMOTE_NETWORK_MANAGER_PUBLIC_INCLUDE_SUFFIX microsoft/net) 6 | set(NET_REMOTE_NETWORK_MANAGER_PUBLIC_INCLUDE_PREFIX ${NET_REMOTE_NETWORK_MANAGER_PUBLIC_INCLUDE}/${NET_REMOTE_NETWORK_MANAGER_PUBLIC_INCLUDE_SUFFIX}) 7 | 8 | target_sources(${PROJECT_NAME}-network-manager 9 | PRIVATE 10 | ${CMAKE_CURRENT_SOURCE_DIR}/NetworkManager.cxx 11 | PUBLIC 12 | FILE_SET HEADERS 13 | BASE_DIRS ${NET_REMOTE_NETWORK_MANAGER_PUBLIC_INCLUDE} 14 | FILES 15 | ${NET_REMOTE_NETWORK_MANAGER_PUBLIC_INCLUDE_PREFIX}/NetworkManager.hxx 16 | ) 17 | 18 | target_link_libraries(${PROJECT_NAME}-network-manager 19 | PUBLIC 20 | ${PROJECT_NAME}-net 21 | wifi-apmanager 22 | wifi-core 23 | ) 24 | 25 | install( 26 | TARGETS ${PROJECT_NAME}-network-manager 27 | EXPORT ${PROJECT_NAME} 28 | COMPONENT dev 29 | FILE_SET HEADERS 30 | PUBLIC_HEADER DESTINATION "${NETREMOTE_DIR_INSTALL_PUBLIC_HEADER_BASE}/${NET_REMOTE_NETWORK_MANAGER_PUBLIC_INCLUDE_SUFFIX}" 31 | ) 32 | -------------------------------------------------------------------------------- /src/common/net/network-manager/NetworkManager.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace Microsoft::Net; 11 | using namespace Microsoft::Net::Wifi; 12 | 13 | NetworkManager::NetworkManager(std::unique_ptr networkOperations, std::shared_ptr accessPointManager) noexcept : 14 | m_networkOperations(std::move(networkOperations)), 15 | m_accessPointManager(std::move(accessPointManager)) 16 | {} 17 | 18 | std::shared_ptr 19 | NetworkManager::GetAccessPointManager() const noexcept 20 | { 21 | return m_accessPointManager; 22 | } 23 | 24 | std::unordered_map> 25 | NetworkManager::GetNetworkInterfaceInformation() const noexcept 26 | { 27 | std::unordered_map> networkInterfaceInfo{}; 28 | 29 | auto networkInterfaces = m_networkOperations->EnumerateNetworkInterfaces(); 30 | for (auto& networkInterfaceId : networkInterfaces) { 31 | auto networkIpAddresses = m_networkOperations->GetNetworkInterfaceAddresses(networkInterfaceId.Name); 32 | networkInterfaceInfo[std::move(networkInterfaceId)] = std::move(networkIpAddresses); 33 | } 34 | 35 | return networkInterfaceInfo; 36 | } 37 | 38 | std::unordered_map 39 | NetworkManager::GetLocalIpAddressInformation(std::string_view ipAddress) const noexcept 40 | { 41 | if (m_networkOperations == nullptr) { 42 | return {}; 43 | } 44 | 45 | return m_networkOperations->GetLocalIpAddressInformation(ipAddress); 46 | } 47 | -------------------------------------------------------------------------------- /src/common/net/service-api/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_subdirectory(adapter) 3 | -------------------------------------------------------------------------------- /src/common/net/service-api/adapter/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_library(${PROJECT_NAME}-net-adapter-service-api STATIC "") 3 | 4 | set(NET_REMOTE_NET_ADAPTER_SERVICE_API_PUBLIC_INCLUDE ${CMAKE_CURRENT_LIST_DIR}/include) 5 | set(NET_REMOTE_NET_ADAPTER_SERVICE_API_PUBLIC_INCLUDE_SUFFIX microsoft/net) 6 | set(NET_REMOTE_NET_ADAPTER_SERVICE_API_PUBLIC_INCLUDE_PREFIX ${NET_REMOTE_NET_ADAPTER_SERVICE_API_PUBLIC_INCLUDE}/${NET_REMOTE_NET_ADAPTER_SERVICE_API_PUBLIC_INCLUDE_SUFFIX}) 7 | 8 | target_sources(${PROJECT_NAME}-net-adapter-service-api 9 | PRIVATE 10 | ServiceApiNetworkAdapters.cxx 11 | ServiceApiNetworkDot1xAdapters.cxx 12 | PUBLIC 13 | FILE_SET HEADERS 14 | BASE_DIRS ${NET_REMOTE_NET_ADAPTER_SERVICE_API_PUBLIC_INCLUDE} 15 | FILES 16 | ${NET_REMOTE_NET_ADAPTER_SERVICE_API_PUBLIC_INCLUDE_PREFIX}/ServiceApiNetworkAdapters.hxx 17 | ${NET_REMOTE_NET_ADAPTER_SERVICE_API_PUBLIC_INCLUDE_PREFIX}/ServiceApiNetworkDot1xAdapters.hxx 18 | ) 19 | 20 | target_link_libraries(${PROJECT_NAME}-net-adapter-service-api 21 | PUBLIC 22 | ${PROJECT_NAME}-protocol 23 | ${PROJECT_NAME}-net 24 | ) 25 | 26 | install( 27 | TARGETS ${PROJECT_NAME}-net-adapter-service-api 28 | EXPORT ${PROJECT_NAME} 29 | COMPONENT dev 30 | FILE_SET HEADERS 31 | PUBLIC_HEADER DESTINATION "${NETREMOTE_DIR_INSTALL_PUBLIC_HEADER_BASE}/${NET_REMOTE_NET_ADAPTER_API_PUBLIC_INCLUDE_SUFFIX}" 32 | ) 33 | -------------------------------------------------------------------------------- /src/common/net/wifi/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_subdirectory(apmanager) 3 | add_subdirectory(core) 4 | add_subdirectory(dot11) 5 | -------------------------------------------------------------------------------- /src/common/net/wifi/apmanager/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_library(wifi-apmanager STATIC "") 3 | 4 | set(WIFI_APMANAGER_PUBLIC_INCLUDE ${CMAKE_CURRENT_LIST_DIR}/include) 5 | set(WIFI_APMANAGER_PUBLIC_INCLUDE_SUFFIX microsoft/net/wifi) 6 | set(WIFI_APMANAGER_PUBLIC_INCLUDE_PREFIX ${WIFI_APMANAGER_PUBLIC_INCLUDE}/${WIFI_APMANAGER_PUBLIC_INCLUDE_SUFFIX}) 7 | 8 | target_sources(wifi-apmanager 9 | PRIVATE 10 | AccessPointManager.cxx 11 | AccessPointDiscoveryAgent.cxx 12 | PUBLIC 13 | FILE_SET HEADERS 14 | BASE_DIRS ${WIFI_APMANAGER_PUBLIC_INCLUDE} 15 | FILES 16 | ${WIFI_APMANAGER_PUBLIC_INCLUDE_PREFIX}/IAccessPointDiscoveryAgentOperations.hxx 17 | ${WIFI_APMANAGER_PUBLIC_INCLUDE_PREFIX}/AccessPointDiscoveryAgent.hxx 18 | ${WIFI_APMANAGER_PUBLIC_INCLUDE_PREFIX}/AccessPointManager.hxx 19 | ) 20 | 21 | target_link_libraries(wifi-apmanager 22 | PRIVATE 23 | notstd 24 | plog::plog 25 | PUBLIC 26 | ${PROJECT_NAME}-protocol 27 | logging-utils 28 | wifi-core 29 | ) 30 | 31 | install( 32 | TARGETS wifi-apmanager 33 | EXPORT ${PROJECT_NAME} 34 | COMPONENT dev 35 | FILE_SET HEADERS 36 | PUBLIC_HEADER DESTINATION "${NETREMOTE_DIR_INSTALL_PUBLIC_HEADER_BASE}/${WIFI_APMANAGER_PUBLIC_INCLUDE_SUFFIX}" 37 | ) 38 | -------------------------------------------------------------------------------- /src/common/net/wifi/core/AccessPointAttributes.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | using namespace Microsoft::Net::Wifi; 11 | 12 | /* static */ 13 | std::optional> 14 | AccessPointAttributes::TryParseJson(const std::string& json) 15 | { 16 | return ParseAccessPointAttributesFromJson(json); 17 | } 18 | 19 | /* static */ 20 | std::optional> 21 | AccessPointAttributes::TryParseJson(std::istream& json) 22 | { 23 | return ParseAccessPointAttributesFromJson(json); 24 | } 25 | -------------------------------------------------------------------------------- /src/common/net/wifi/core/AccessPointAttributesJsonSerialization.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | namespace Microsoft::Net::Wifi 7 | { 8 | void 9 | to_json(nlohmann::json& accessPointAttributesJson, const AccessPointAttributes& accessPointAttributes) 10 | { 11 | accessPointAttributesJson = nlohmann::json{ 12 | { "Properties", accessPointAttributes.Properties } 13 | }; 14 | } 15 | 16 | void 17 | from_json(const nlohmann::json& accessPointAttributesJson, AccessPointAttributes& accessPointAttributes) 18 | { 19 | accessPointAttributesJson.at("Properties").get_to(accessPointAttributes.Properties); 20 | } 21 | 22 | } // namespace Microsoft::Net::Wifi 23 | -------------------------------------------------------------------------------- /src/common/net/wifi/core/AccessPointController.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #include 5 | 6 | using namespace Microsoft::Net::Wifi; 7 | 8 | AccessPointController::AccessPointController(std::string_view interface) : 9 | m_interfaceName(interface) 10 | { 11 | } 12 | 13 | std::string_view 14 | AccessPointController::GetInterfaceName() const noexcept 15 | { 16 | return m_interfaceName; 17 | } 18 | -------------------------------------------------------------------------------- /src/common/net/wifi/core/AccessPointOperationStatusLogOnExit.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace Microsoft::Net::Wifi; 8 | 9 | AccessPointOperationStatusLogOnExit::AccessPointOperationStatusLogOnExit(AccessPointOperationStatus* operationStatus, plog::Severity severityOnError, plog::Severity severityOnSuccess) noexcept : 10 | OperationStatus(operationStatus), 11 | SeverityOnError(severityOnError), 12 | SeverityOnSuccess(severityOnSuccess) 13 | { 14 | } 15 | 16 | AccessPointOperationStatusLogOnExit::~AccessPointOperationStatusLogOnExit() 17 | { 18 | if (OperationStatus != nullptr) { 19 | LOG(OperationStatus->Succeeded() ? SeverityOnSuccess : SeverityOnError) << OperationStatus->ToString(); 20 | } 21 | } 22 | 23 | void 24 | AccessPointOperationStatusLogOnExit::Reset() noexcept 25 | { 26 | OperationStatus = nullptr; 27 | } 28 | -------------------------------------------------------------------------------- /src/common/net/wifi/core/Ieee80211AccessPointCapabilities.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | using namespace Microsoft::Net::Wifi; 9 | 10 | std::string 11 | Ieee80211AccessPointCapabilities::ToString() const 12 | { 13 | std::ostringstream result{}; 14 | 15 | result << "Security Protocols: "; 16 | for (const auto& securityProtocol : SecurityProtocols) { 17 | result << magic_enum::enum_name(securityProtocol); 18 | result << ' '; 19 | } 20 | 21 | result << '\n' 22 | << "PHY Types: "; 23 | for (const auto& phyType : PhyTypes) { 24 | result << magic_enum::enum_name(phyType); 25 | result << ' '; 26 | } 27 | 28 | result << '\n' 29 | << "Frequency Bands: "; 30 | for (const auto& frequencyBand : FrequencyBands) { 31 | result << magic_enum::enum_name(frequencyBand); 32 | result << ' '; 33 | } 34 | 35 | result << '\n' 36 | << "Akm Suites: "; 37 | for (const auto& akmSuite : AkmSuites) { 38 | result << magic_enum::enum_name(akmSuite); 39 | result << ' '; 40 | } 41 | 42 | result << '\n' 43 | << "Cipher Suites: "; 44 | for (const auto& cipherSuite : CipherSuites) { 45 | result << magic_enum::enum_name(cipherSuite); 46 | result << ' '; 47 | } 48 | result << '\n'; 49 | 50 | return result.str(); 51 | } 52 | -------------------------------------------------------------------------------- /src/common/net/wifi/core/Ieee80211Authentication.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | using namespace Microsoft::Net::Wifi; 12 | 13 | std::string 14 | Ieee80211RsnaPsk::ToHexEncodedValue() const 15 | { 16 | assert(Encoding() == Ieee80211RsnaPskEncoding::Value); 17 | 18 | std::string valueHexEncoded; 19 | { 20 | const auto& value = Value(); 21 | std::ostringstream valueHexEncodedBuilder; 22 | std::ranges::for_each(value, [&](std::uint8_t valueByte) { 23 | valueHexEncodedBuilder << std::format("{:02X}", valueByte); 24 | }); 25 | 26 | valueHexEncoded = valueHexEncodedBuilder.str(); 27 | } 28 | 29 | return valueHexEncoded; 30 | } 31 | -------------------------------------------------------------------------------- /src/common/net/wifi/core/include/microsoft/net/wifi/AccessPointAttributes.hxx: -------------------------------------------------------------------------------- 1 | 2 | #ifndef ACCESS_POINT_ATTRIBUTES_HXX 3 | #define ACCESS_POINT_ATTRIBUTES_HXX 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace Microsoft::Net::Wifi 11 | { 12 | /** 13 | * @brief Container to hold static attributes about an access point. 14 | */ 15 | struct AccessPointAttributes 16 | { 17 | std::unordered_map Properties{}; 18 | 19 | bool 20 | operator==(const AccessPointAttributes&) const = default; 21 | 22 | /** 23 | * @brief Attempt to deserialize a JSON string into a map of access point attributes. 24 | * 25 | * @param json The JSON input string to parse. 26 | * @return std::optional> 27 | */ 28 | static std::optional> 29 | TryParseJson(const std::string& json); 30 | 31 | /** 32 | * @brief Attempt to deserialize a JSON stream into a map of access point attributes. 33 | * 34 | * @param json The JSON input stream to parse. 35 | * @return std::optional> 36 | */ 37 | static std::optional> 38 | TryParseJson(std::istream& json); 39 | }; 40 | } // namespace Microsoft::Net::Wifi 41 | 42 | #endif // ACCESS_POINT_ATTRIBUTES_HXX 43 | -------------------------------------------------------------------------------- /src/common/net/wifi/core/include/microsoft/net/wifi/AccessPointController.hxx: -------------------------------------------------------------------------------- 1 | 2 | #ifndef ACCESS_POINT_CONTROLLER_HXX 3 | #define ACCESS_POINT_CONTROLLER_HXX 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | namespace Microsoft::Net::Wifi 11 | { 12 | /** 13 | * @brief Implementation of IAccessPointController for operations that should be 14 | * common to all implementations. 15 | */ 16 | struct AccessPointController : 17 | public IAccessPointController 18 | { 19 | virtual ~AccessPointController() = default; 20 | 21 | /** 22 | * @brief Construct a new AccessPointController object to control the specified interface. 23 | * 24 | * @param interfaceName 25 | */ 26 | AccessPointController(std::string_view interfaceName); 27 | 28 | /** 29 | * @brief Get the interface name associated with this controller. 30 | * 31 | * @return std::string_view 32 | */ 33 | std::string_view 34 | GetInterfaceName() const noexcept override; 35 | 36 | private: 37 | std::string m_interfaceName; 38 | }; 39 | } // namespace Microsoft::Net::Wifi 40 | 41 | #endif // ACCESS_POINT_CONTROLLER_HXX 42 | -------------------------------------------------------------------------------- /src/common/net/wifi/core/include/microsoft/net/wifi/Ieee80211AccessPointCapabilities.hxx: -------------------------------------------------------------------------------- 1 | 2 | #ifndef IEEE_80211_ACCESS_POINT_CAPABILITIES_HXX 3 | #define IEEE_80211_ACCESS_POINT_CAPABILITIES_HXX 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | namespace Microsoft::Net::Wifi 11 | { 12 | /** 13 | * @brief Describes the capabilities of an IEEE 802.11 access point. 14 | */ 15 | struct Ieee80211AccessPointCapabilities 16 | { 17 | std::vector SecurityProtocols{}; 18 | std::vector PhyTypes{}; 19 | std::vector FrequencyBands{}; 20 | std::vector AkmSuites{}; 21 | std::vector CipherSuites{}; 22 | 23 | /** 24 | * @brief Get a string representation of the capabilities. 25 | * 26 | * @return std::string 27 | */ 28 | std::string 29 | ToString() const; 30 | }; 31 | } // namespace Microsoft::Net::Wifi 32 | 33 | #endif // IEEE_80211_ACCESS_POINT_CAPABILITIES_HXX 34 | -------------------------------------------------------------------------------- /src/common/net/wifi/core/include/microsoft/net/wifi/Ieee80211AccessPointConfiguration.hxx: -------------------------------------------------------------------------------- 1 | 2 | #ifndef IEEE_80211_ACCESS_POINT_CONFIGURATION 3 | #define IEEE_80211_ACCESS_POINT_CONFIGURATION 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | namespace Microsoft::Net::Wifi 14 | { 15 | /** 16 | * @brief Configuration for an IEEE 802.11 access point. 17 | */ 18 | struct Ieee80211AccessPointConfiguration 19 | { 20 | std::optional Ssid; 21 | std::optional Bssid; 22 | std::optional PhyType; 23 | std::vector AkmSuites; 24 | std::unordered_map> PairwiseCipherSuites; 25 | std::vector AuthenticationAlgorithms; 26 | std::vector FrequencyBands; 27 | Ieee80211AuthenticationData AuthenticationData; 28 | }; 29 | } // namespace Microsoft::Net::Wifi 30 | 31 | #endif // IEEE_80211_ACCESS_POINT_CONFIGURATION 32 | -------------------------------------------------------------------------------- /src/common/net/wifi/dot11/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_subdirectory(adapter) 3 | -------------------------------------------------------------------------------- /src/common/net/wifi/dot11/adapter/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_library(wifi-core-adapter-dot11 STATIC "") 3 | 4 | set(WIFI_CORE_ADAPTER_DOT11_PUBLIC_INCLUDE ${CMAKE_CURRENT_LIST_DIR}/include) 5 | set(WIFI_CORE_ADAPTER_DOT11_PUBLIC_INCLUDE_SUFFIX microsoft/net/wifi) 6 | set(WIFI_CORE_ADAPTER_DOT11_PUBLIC_INCLUDE_PREFIX ${WIFI_CORE_ADAPTER_DOT11_PUBLIC_INCLUDE}/${WIFI_CORE_ADAPTER_DOT11_PUBLIC_INCLUDE_SUFFIX}) 7 | 8 | target_sources(wifi-core-adapter-dot11 9 | PRIVATE 10 | Ieee80211Dot11Adapters.cxx 11 | PUBLIC 12 | FILE_SET HEADERS 13 | BASE_DIRS ${WIFI_CORE_ADAPTER_DOT11_PUBLIC_INCLUDE} 14 | FILES 15 | ${WIFI_CORE_ADAPTER_DOT11_PUBLIC_INCLUDE_PREFIX}/Ieee80211Dot11Adapters.hxx 16 | ) 17 | 18 | target_link_libraries(wifi-core-adapter-dot11 19 | PUBLIC 20 | ${PROJECT_NAME}-net-adapter-service-api 21 | ${PROJECT_NAME}-protocol 22 | wifi-core 23 | PRIVATE 24 | notstd 25 | strings 26 | ) 27 | 28 | install( 29 | TARGETS wifi-core-adapter-dot11 30 | EXPORT ${PROJECT_NAME} 31 | COMPONENT dev 32 | FILE_SET HEADERS 33 | PUBLIC_HEADER DESTINATION "${NETREMOTE_DIR_INSTALL_PUBLIC_HEADER_BASE}/${WIFI_CORE_ADAPTER_DOT11_PUBLIC_INCLUDE_SUFFIX}" 34 | ) 35 | 36 | -------------------------------------------------------------------------------- /src/common/rfattenuator/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(${PROJECT_NAME}-rfattenuator-interface INTERFACE) 2 | 3 | set(RFATTENUATOR_INTERFACE_PUBLIC_INCLUDE ${CMAKE_CURRENT_LIST_DIR}/include) 4 | set(RFATTENUATOR_INTERFACE_PUBLIC_INCLUDE_SUFFIX microsoft/net/remote/service) 5 | set(RFATTENUATOR_INTERFACE_PUBLIC_INCLUDE_PREFIX ${RFATTENUATOR_INTERFACE_PUBLIC_INCLUDE}/${RFATTENUATOR_INTERFACE_PUBLIC_INCLUDE_SUFFIX}) 6 | 7 | target_sources(${PROJECT_NAME}-rfattenuator-interface 8 | PUBLIC 9 | FILE_SET HEADERS 10 | BASE_DIRS ${RFATTENUATOR_INTERFACE_PUBLIC_INCLUDE} 11 | FILES 12 | ${RFATTENUATOR_INTERFACE_PUBLIC_INCLUDE_PREFIX}/RfAttenuator.hxx 13 | ) 14 | 15 | install( 16 | TARGETS ${PROJECT_NAME}-rfattenuator-interface 17 | EXPORT ${PROJECT_NAME} 18 | COMPONENT dev 19 | FILE_SET HEADERS 20 | PUBLIC_HEADER DESTINATION "${NETREMOTE_DIR_INSTALL_PUBLIC_HEADER_BASE}/{RFATTENUATOR-INTERFACE_PUBLIC_INCLUDE_SUFFIX}" 21 | ) 22 | -------------------------------------------------------------------------------- /src/common/server/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_library(${PROJECT_NAME}-server STATIC "") 3 | 4 | set(NET_REMOTE_SERVER_PUBLIC_INCLUDE ${CMAKE_CURRENT_LIST_DIR}/include) 5 | set(NET_REMOTE_SERVER_PUBLIC_INCLUDE_SUFFIX microsoft/net/remote/service) 6 | set(NET_REMOTE_SERVER_PUBLIC_INCLUDE_PREFIX ${NET_REMOTE_SERVER_PUBLIC_INCLUDE}/${NET_REMOTE_SERVER_PUBLIC_INCLUDE_SUFFIX}) 7 | 8 | target_sources(${PROJECT_NAME}-server 9 | PRIVATE 10 | NetRemoteServer.cxx 11 | NetRemoteServerConfiguration.cxx 12 | NetRemoteServerJsonConfiguration.cxx 13 | PUBLIC 14 | FILE_SET HEADERS 15 | BASE_DIRS ${NET_REMOTE_SERVER_PUBLIC_INCLUDE} 16 | FILES 17 | ${NET_REMOTE_SERVER_PUBLIC_INCLUDE_PREFIX}/NetRemoteServer.hxx 18 | ${NET_REMOTE_SERVER_PUBLIC_INCLUDE_PREFIX}/NetRemoteServerConfiguration.hxx 19 | ${NET_REMOTE_SERVER_PUBLIC_INCLUDE_PREFIX}/NetRemoteServerJsonConfiguration.hxx 20 | ) 21 | 22 | target_link_libraries(${PROJECT_NAME}-server 23 | PUBLIC 24 | ${PROJECT_NAME}-network-manager 25 | ${PROJECT_NAME}-service 26 | PRIVATE 27 | CLI11::CLI11 28 | nlohmann_json::nlohmann_json 29 | plog::plog 30 | ) 31 | 32 | install( 33 | TARGETS ${PROJECT_NAME}-server 34 | EXPORT ${PROJECT_NAME} 35 | COMPONENT dev 36 | FILE_SET HEADERS 37 | PUBLIC_HEADER DESTINATION "${NETREMOTE_DIR_INSTALL_PUBLIC_HEADER_BASE}/${NET_REMOTE_SERVER_PUBLIC_INCLUDE_SUFFIX}" 38 | ) 39 | -------------------------------------------------------------------------------- /src/common/server/config/netremote-server-config-example.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../../../config/netremote-server-config-schema.json", 3 | "WifiAccessPointAttributes": { 4 | "Properties": { 5 | "wlan0": { 6 | "MacAddress": "00:11:22:33:44:55", 7 | "RfAttenuatorChannelsAttached": "1,3" 8 | }, 9 | "wlp0s3": { 10 | "MacAddress": "AA:BB:CC:DD:EE:FF", 11 | "RfAttenuatorChannelsAttached": "2,4,6", 12 | "Another": "String value" 13 | } 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /src/common/service/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_library(${PROJECT_NAME}-service STATIC "") 3 | 4 | set(NET_REMOTE_SERVICE_PUBLIC_INCLUDE ${CMAKE_CURRENT_LIST_DIR}/include) 5 | set(NET_REMOTE_SERVICE_PUBLIC_INCLUDE_SUFFIX microsoft/net/remote/service) 6 | set(NET_REMOTE_SERVICE_PUBLIC_INCLUDE_PREFIX ${NET_REMOTE_SERVICE_PUBLIC_INCLUDE}/${NET_REMOTE_SERVICE_PUBLIC_INCLUDE_SUFFIX}) 7 | 8 | target_sources(${PROJECT_NAME}-service 9 | PRIVATE 10 | NetRemoteApiTrace.cxx 11 | NetRemoteApiTrace.hxx 12 | NetRemoteDataStreamingReactors.cxx 13 | NetRemoteDataStreamingReactors.hxx 14 | NetRemoteDataStreamingService.cxx 15 | NetRemoteDiscoveryService.cxx 16 | NetRemoteRfAttenuatorService.cxx 17 | NetRemoteService.cxx 18 | NetRemoteWifiApiTrace.cxx 19 | NetRemoteWifiApiTrace.hxx 20 | PUBLIC 21 | FILE_SET HEADERS 22 | BASE_DIRS ${NET_REMOTE_SERVICE_PUBLIC_INCLUDE} 23 | FILES 24 | ${NET_REMOTE_SERVICE_PUBLIC_INCLUDE_PREFIX}/NetRemoteDataStreamingService.hxx 25 | ${NET_REMOTE_SERVICE_PUBLIC_INCLUDE_PREFIX}/NetRemoteDiscoveryService.hxx 26 | ${NET_REMOTE_SERVICE_PUBLIC_INCLUDE_PREFIX}/NetRemoteService.hxx 27 | ${NET_REMOTE_SERVICE_PUBLIC_INCLUDE_PREFIX}/NetRemoteRfAttenuatorService.hxx 28 | ) 29 | 30 | target_link_libraries(${PROJECT_NAME}-service 31 | PUBLIC 32 | ${PROJECT_NAME}-network-manager 33 | ${PROJECT_NAME}-protocol 34 | wifi-apmanager 35 | ${PROJECT_NAME}-rfattenuator-interface 36 | PRIVATE 37 | ${PROJECT_NAME}-net-adapter-service-api 38 | logging-utils 39 | plog::plog 40 | wifi-core-adapter-dot11 41 | ) 42 | 43 | install( 44 | TARGETS ${PROJECT_NAME}-service 45 | EXPORT ${PROJECT_NAME} 46 | COMPONENT dev 47 | FILE_SET HEADERS 48 | PUBLIC_HEADER DESTINATION "${NETREMOTE_DIR_INSTALL_PUBLIC_HEADER_BASE}/${NET_REMOTE_SERVICE_PUBLIC_INCLUDE_SUFFIX}" 49 | ) 50 | -------------------------------------------------------------------------------- /src/common/service/NetRemoteApiTrace.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | #include "NetRemoteApiTrace.hxx" 8 | 9 | using namespace Microsoft::Net::Remote::Service::Tracing; 10 | 11 | NetRemoteApiTrace::NetRemoteApiTrace(bool deferEnter, plog::Severity logSeverity, std::source_location location) : 12 | logging::FunctionTracer(logSeverity, LogTracePrefix, {}, deferEnter, location) 13 | {} 14 | -------------------------------------------------------------------------------- /src/common/service/NetRemoteApiTrace.hxx: -------------------------------------------------------------------------------- 1 | 2 | #ifndef NET_REMOTE_API_TRACE_HXX 3 | #define NET_REMOTE_API_TRACE_HXX 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | namespace Microsoft::Net::Remote::Service::Tracing 11 | { 12 | /** 13 | * @brief Netremote API function tracer. 14 | */ 15 | struct NetRemoteApiTrace : 16 | public logging::FunctionTracer 17 | { 18 | /** 19 | * @brief Construct a new NetRemoteApiTrace object. 20 | * 21 | * @param deferEnter Whether to defer the entry log message upon construction. 22 | * @param logSeverity The default log severity to use when tracing. 23 | * @param location The source code location of the function call. 24 | */ 25 | NetRemoteApiTrace(bool deferEnter = false, plog::Severity logSeverity = LogSeverityDefaultApi, std::source_location location = std::source_location::current()); 26 | 27 | protected: 28 | static constexpr auto LogSeverityDefaultApi{ plog::Severity::info }; 29 | 30 | private: 31 | static constexpr auto LogTracePrefix = "[API]"; 32 | }; 33 | 34 | } // namespace Microsoft::Net::Remote::Service::Tracing 35 | 36 | #endif // NET_REMOTE_API_TRACE_HXX 37 | -------------------------------------------------------------------------------- /src/common/service/NetRemoteDataStreamingService.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "NetRemoteApiTrace.hxx" 11 | #include "NetRemoteDataStreamingReactors.hxx" 12 | 13 | using namespace Microsoft::Net::Remote::DataStream; 14 | using namespace Microsoft::Net::Remote::Service; 15 | using namespace Microsoft::Net::Remote::Service::Tracing; 16 | 17 | grpc::ServerReadReactor* 18 | NetRemoteDataStreamingService::DataStreamUpload([[maybe_unused]] grpc::CallbackServerContext* context, DataStreamUploadResult* result) 19 | { 20 | const NetRemoteApiTrace traceMe{}; 21 | 22 | return std::make_unique(result).release(); 23 | } 24 | 25 | grpc::ServerWriteReactor* 26 | NetRemoteDataStreamingService::DataStreamDownload([[maybe_unused]] grpc::CallbackServerContext* context, const DataStreamDownloadRequest* request) 27 | { 28 | const NetRemoteApiTrace traceMe{}; 29 | 30 | return std::make_unique(request).release(); 31 | } 32 | 33 | grpc::ServerBidiReactor* 34 | NetRemoteDataStreamingService::DataStreamBidirectional([[maybe_unused]] grpc::CallbackServerContext* context) 35 | { 36 | const NetRemoteApiTrace traceMe{}; 37 | 38 | return std::make_unique().release(); 39 | } 40 | 41 | grpc::ServerUnaryReactor* 42 | NetRemoteDataStreamingService::DataStreamPing(grpc::CallbackServerContext* context, [[maybe_unused]] const google::protobuf::Empty* request, [[maybe_unused]] google::protobuf::Empty* response) 43 | { 44 | const NetRemoteApiTrace traceMe{}; 45 | 46 | auto* reactor = context->DefaultReactor(); 47 | reactor->Finish(grpc::Status::OK); 48 | 49 | return reactor; 50 | } 51 | -------------------------------------------------------------------------------- /src/common/service/NetRemoteDiscoveryService.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace Microsoft::Net::Remote::Service; 17 | using Microsoft::Net::INetworkOperations; 18 | using Microsoft::Net::IpAddressInformation; 19 | 20 | NetRemoteDiscoveryService::NetRemoteDiscoveryService(NetRemoteDiscoveryServiceConfiguration discoveryServiceConfiguration) : 21 | m_configuration(std::move(discoveryServiceConfiguration)) 22 | {} 23 | 24 | std::string_view 25 | NetRemoteDiscoveryService::GetServiceName() const noexcept 26 | { 27 | return m_configuration.Name; 28 | } 29 | 30 | std::string_view 31 | NetRemoteDiscoveryService::GetProtocol() const noexcept 32 | { 33 | return m_configuration.Protocol; 34 | } 35 | 36 | uint16_t 37 | NetRemoteDiscoveryService::GetPort() const noexcept 38 | { 39 | return m_configuration.Port; 40 | } 41 | 42 | const std::unordered_map& 43 | NetRemoteDiscoveryService::GetIpAddresses() const noexcept 44 | { 45 | return m_configuration.IpAddresses; 46 | } 47 | -------------------------------------------------------------------------------- /src/common/service/NetRemoteWifiApiTrace.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include "NetRemoteApiTrace.hxx" 12 | #include "NetRemoteWifiApiTrace.hxx" 13 | 14 | using namespace Microsoft::Net::Remote::Service::Tracing; 15 | 16 | using Microsoft::Net::Remote::Wifi::WifiAccessPointOperationStatus; 17 | using Microsoft::Net::Remote::Wifi::WifiAccessPointOperationStatusCode; 18 | 19 | NetRemoteWifiApiTrace::NetRemoteWifiApiTrace(std::optional accessPointId, const WifiAccessPointOperationStatus* operationStatus, plog::Severity logSeverity, std::source_location location) : 20 | NetRemoteApiTrace(/* deferEnter= */ true, logSeverity, location), 21 | m_accessPointId(std::move(accessPointId)), 22 | m_operationStatus(operationStatus) 23 | { 24 | if (m_accessPointId.has_value()) { 25 | AddArgument(ArgNameAccessPointId, m_accessPointId.value()); 26 | } 27 | 28 | Enter(); 29 | } 30 | 31 | NetRemoteWifiApiTrace::~NetRemoteWifiApiTrace() 32 | { 33 | if (m_operationStatus == nullptr) { 34 | return; 35 | } 36 | 37 | AddReturnValue(ArgNameStatus, std::string(magic_enum::enum_name(m_operationStatus->code()))); 38 | 39 | if (m_operationStatus->code() != WifiAccessPointOperationStatusCode::WifiAccessPointOperationStatusCodeSucceeded) { 40 | AddReturnValue(ArgNameErrorMessage, m_operationStatus->message()); 41 | SetFailed(); 42 | } else { 43 | SetSucceeded(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/common/service/NetRemoteWifiApiTrace.hxx: -------------------------------------------------------------------------------- 1 | 2 | #ifndef NET_REMOTE_WIFI_API_TRACE_HXX 3 | #define NET_REMOTE_WIFI_API_TRACE_HXX 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "NetRemoteApiTrace.hxx" 14 | 15 | namespace Microsoft::Net::Remote::Service::Tracing 16 | { 17 | /** 18 | * @brief Netremote Wi-Fi API function tracer. This should be used for all Wi-Fi API calls. It accepts arguments and 19 | * return values as optionals and/or pointers to indicate their presence. 20 | */ 21 | struct NetRemoteWifiApiTrace : 22 | public NetRemoteApiTrace 23 | { 24 | /** 25 | * @brief Construct a new Net RemoteWifiApiTrace object. 26 | * 27 | * @param accessPointId The access point id associated with the API request, if present. 28 | * @param operationStatus The result status of the operation, if present. 29 | * @param location The source code location of the function call. 30 | */ 31 | NetRemoteWifiApiTrace(std::optional accessPointId = std::nullopt, const Microsoft::Net::Remote::Wifi::WifiAccessPointOperationStatus* operationStatus = nullptr, plog::Severity logSeverity = LogSeverityDefaultApi, std::source_location location = std::source_location::current()); 32 | 33 | /** 34 | * @brief Destroy the NetRemoteWifiApiTrace object. 35 | */ 36 | virtual ~NetRemoteWifiApiTrace(); 37 | 38 | private: 39 | std::optional m_accessPointId; 40 | const Microsoft::Net::Remote::Wifi::WifiAccessPointOperationStatus* m_operationStatus{ nullptr }; 41 | 42 | static constexpr auto ArgNameAccessPointId{ "Access Point" }; 43 | static constexpr auto ArgNameErrorMessage{ "Error Message" }; 44 | static constexpr auto ArgNameStatus{ "Status" }; 45 | }; 46 | } // namespace Microsoft::Net::Remote::Service::Tracing 47 | 48 | #endif // NET_REMOTE_WIFI_API_TRACE_HXX 49 | -------------------------------------------------------------------------------- /src/common/shared/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_subdirectory(logging) 3 | add_subdirectory(notstd) 4 | add_subdirectory(strings) 5 | -------------------------------------------------------------------------------- /src/common/shared/logging/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_library(logging-utils STATIC "") 3 | 4 | set(LOGUTILS_DIR_PUBLIC_INCLUDE ${CMAKE_CURRENT_LIST_DIR}/include) 5 | set(LOGUTILS_DIR_PUBLIC_INCLUDE_SUFFIX logging) 6 | set(LOGUTILS_DIR_PUBLIC_INCLUDE_PREFIX ${LOGUTILS_DIR_PUBLIC_INCLUDE}/${LOGUTILS_DIR_PUBLIC_INCLUDE_SUFFIX}) 7 | 8 | target_sources(logging-utils 9 | PRIVATE 10 | ${CMAKE_CURRENT_LIST_DIR}/FunctionTracer.cxx 11 | ${CMAKE_CURRENT_LIST_DIR}/LogUtils.cxx 12 | PUBLIC 13 | FILE_SET HEADERS 14 | BASE_DIRS ${LOGUTILS_DIR_PUBLIC_INCLUDE} 15 | FILES 16 | ${LOGUTILS_DIR_PUBLIC_INCLUDE_PREFIX}/FunctionTracer.hxx 17 | ${LOGUTILS_DIR_PUBLIC_INCLUDE_PREFIX}/LogUtils.hxx 18 | ) 19 | 20 | target_link_libraries(logging-utils 21 | PUBLIC 22 | plog::plog 23 | ) 24 | 25 | install( 26 | TARGETS logging-utils 27 | EXPORT ${PROJECT_NAME} 28 | COMPONENT dev 29 | FILE_SET HEADERS 30 | PUBLIC_HEADER DESTINATION "${NETREMOTE_DIR_INSTALL_PUBLIC_HEADER_BASE}/${LOGUTILS_DIR_PUBLIC_INCLUDE_SUFFIX}" 31 | ) 32 | -------------------------------------------------------------------------------- /src/common/shared/logging/LogUtils.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | std::string 14 | logging::GetLogName(std::string_view componentName) 15 | { 16 | const auto now = std::chrono::system_clock::now(); 17 | const std::time_t t_c = std::chrono::system_clock::to_time_t(now); 18 | 19 | std::stringstream ss; 20 | 21 | ss << std::put_time(std::localtime(&t_c), "%Y%m%d") // NOLINT(concurrency-mt-unsafe) 22 | << "-LogNetRemote-" 23 | << componentName 24 | << ".txt"; 25 | 26 | return ss.str(); 27 | } 28 | 29 | plog::Severity 30 | logging::LogVerbosityToPlogSeverity(uint32_t verbosity) noexcept 31 | { 32 | switch (verbosity) { 33 | case 0: 34 | return plog::fatal; 35 | case 1: 36 | return plog::error; 37 | case 2: 38 | return plog::warning; 39 | case 3: 40 | return plog::info; 41 | case 4: 42 | return plog::debug; 43 | case 5: 44 | default: 45 | return plog::verbose; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/common/shared/logging/include/logging/LogUtils.hxx: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LOG_UTILS_HXX 3 | #define LOG_UTILS_HXX 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | enum class LogInstanceId : int { 12 | // Default logger is 0 and is omitted from this enumeration. 13 | Console = 1, 14 | File = 2, 15 | Audit = 3, 16 | }; 17 | 18 | #define AUDITN LOG_(static_cast(LogInstanceId::Audit), plog::none) 19 | #define AUDITF LOG_(static_cast(LogInstanceId::Audit), plog::fatal) 20 | #define AUDITE LOG_(static_cast(LogInstanceId::Audit), plog::error) 21 | #define AUDITW LOG_(static_cast(LogInstanceId::Audit), plog::warning) 22 | #define AUDITI LOG_(static_cast(LogInstanceId::Audit), plog::info) 23 | #define AUDITD LOG_(static_cast(LogInstanceId::Audit), plog::debug) 24 | #define AUDITV LOG_(static_cast(LogInstanceId::Audit), plog::verbose) 25 | 26 | namespace logging 27 | { 28 | /** 29 | * @brief Returns the name of the log file to be used. 30 | * Format is -LogNetRemote-.txt 31 | * For example, if the date was Jan 2, 2023 and the componentName was 'server', 32 | * then the name would be '20230102-LogNetRemote-server.txt'. 33 | * 34 | * @param componentName The name of the component the log is for. Eg. 'server', 'client', etc. 35 | * @return std::string 36 | */ 37 | std::string 38 | GetLogName(std::string_view componentName); 39 | 40 | /** 41 | * @brief Converts a log verbosity level to a plog severity level. 42 | * 43 | * @param verbosity The log verbosity level. 44 | * @return plog::Severity 45 | */ 46 | plog::Severity 47 | LogVerbosityToPlogSeverity(uint32_t verbosity) noexcept; 48 | 49 | } // namespace logging 50 | 51 | #endif // LOG_UTILS_HXX 52 | -------------------------------------------------------------------------------- /src/common/shared/notstd/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_library(notstd INTERFACE) 3 | 4 | set(NOTSTD_PUBLIC_INCLUDE ${CMAKE_CURRENT_LIST_DIR}/include) 5 | set(NOTSTD_PUBLIC_INCLUDE_SUFFIX notstd) 6 | set(NOTSTD_PUBLIC_INCLUDE_PREFIX ${NOTSTD_PUBLIC_INCLUDE}/${NOTSTD_PUBLIC_INCLUDE_SUFFIX}) 7 | 8 | target_sources(notstd 9 | PUBLIC 10 | FILE_SET HEADERS 11 | BASE_DIRS ${NOTSTD_PUBLIC_INCLUDE} 12 | FILES 13 | ${NOTSTD_PUBLIC_INCLUDE_PREFIX}/Exceptions.hxx 14 | ${NOTSTD_PUBLIC_INCLUDE_PREFIX}/Memory.hxx 15 | ${NOTSTD_PUBLIC_INCLUDE_PREFIX}/Scope.hxx 16 | ) 17 | 18 | install( 19 | TARGETS notstd 20 | EXPORT ${PROJECT_NAME} 21 | COMPONENT dev 22 | FILE_SET HEADERS 23 | PUBLIC_HEADER DESTINATION "${NETREMOTE_DIR_INSTALL_PUBLIC_HEADER_BASE}/{NOTSTD_PUBLIC_INCLUDE_SUFFIX}" 24 | ) 25 | -------------------------------------------------------------------------------- /src/common/shared/notstd/include/notstd/Exceptions.hxx: -------------------------------------------------------------------------------- 1 | 2 | #ifndef NOTSTD_EXCEPTIONS_HXX 3 | #define NOTSTD_EXCEPTIONS_HXX 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | namespace notstd 12 | { 13 | /** 14 | * @brief Simple exception to indicate a function is not implemented. 15 | */ 16 | struct NotImplementedException : 17 | public std::logic_error 18 | { 19 | explicit NotImplementedException(std::source_location location = std::source_location::current(), std::string_view message = "") : 20 | std::logic_error(std::format("{}({}:{}) `{}` not implemented {}", location.file_name(), location.line(), location.column(), location.function_name(), (!std::empty(message) ? std::string(": ").append(message) : ""))) 21 | { 22 | } 23 | }; 24 | } // namespace notstd 25 | 26 | #endif // NOTSTD_EXCEPTIONS_HXX 27 | -------------------------------------------------------------------------------- /src/common/shared/notstd/include/notstd/Memory.hxx: -------------------------------------------------------------------------------- 1 | 2 | #ifndef NOT_STD_MEMORY_HXX 3 | #define NOT_STD_MEMORY_HXX 4 | 5 | #include 6 | 7 | namespace notstd 8 | { 9 | /** 10 | * @brief Enables use of std::make_unique and std::make_shared for types with 11 | * protected constructors. 12 | * 13 | * This is achieved by sub-classing from the base type (BaseT). Since this type 14 | * derives from the base, it can access all protected members, including the 15 | * constructor. Thus, the internals of std::make_ can invoke 16 | * the protected constructor. 17 | * 18 | * This is useful for classes where std::enable_shared_from_this() is used where 19 | * the constructor must be hidden to prevent creation of non shared_ptr 20 | * instances. 21 | * 22 | * @tparam T The type to allow std::make_unique or std::make_shared access to 23 | * the protected constructor. 24 | */ 25 | template 26 | struct enable_make_protected : public BaseT 27 | { 28 | template 29 | explicit enable_make_protected(TArgs &&...args) : 30 | BaseT(std::forward(args)...) 31 | {} 32 | }; 33 | 34 | } // namespace notstd 35 | 36 | #endif // NOT_STD_MEMORY_HXX 37 | -------------------------------------------------------------------------------- /src/common/shared/strings/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_library(strings STATIC "") 3 | 4 | set(STRINGS_PUBLIC_INCLUDE ${CMAKE_CURRENT_LIST_DIR}/include) 5 | set(STRINGS_PUBLIC_INCLUDE_SUFFIX strings) 6 | set(STRINGS_PUBLIC_INCLUDE_PREFIX ${STRINGS_PUBLIC_INCLUDE}/${STRINGS_PUBLIC_INCLUDE_SUFFIX}) 7 | 8 | target_sources(strings 9 | PRIVATE 10 | ${CMAKE_CURRENT_LIST_DIR}/StringHelpers.cxx 11 | PUBLIC 12 | FILE_SET HEADERS 13 | BASE_DIRS ${STRINGS_PUBLIC_INCLUDE} 14 | FILES 15 | ${STRINGS_PUBLIC_INCLUDE_PREFIX}/StringHelpers.hxx 16 | ${STRINGS_PUBLIC_INCLUDE_PREFIX}/StringParsing.hxx 17 | ) 18 | 19 | install( 20 | TARGETS strings 21 | EXPORT ${PROJECT_NAME} 22 | COMPONENT dev 23 | FILE_SET HEADERS 24 | PUBLIC_HEADER DESTINATION "${NETREMOTE_DIR_INSTALL_PUBLIC_HEADER_BASE}/${STRINGS_PUBLIC_INCLUDE_SUFFIX}" 25 | ) 26 | -------------------------------------------------------------------------------- /src/common/shared/strings/StringHelpers.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | namespace Strings 12 | { 13 | std::string 14 | ToLower(std::string s) 15 | { 16 | std::ranges::transform(s, std::begin(s), [](auto c) { 17 | return ToLower(c); 18 | }); 19 | 20 | return s; 21 | } 22 | 23 | bool 24 | CaseInsensitiveCharEquals(char lhs, char rhs) 25 | { 26 | return ToLower(lhs) == ToLower(rhs); 27 | } 28 | 29 | bool 30 | CaseInsensitiveStringEquals(std::string_view lhs, std::string_view rhs) 31 | { 32 | return std::ranges::equal(lhs, rhs, CaseInsensitiveCharEquals); 33 | } 34 | 35 | std::string 36 | GenerateRandomAsciiString(std::size_t length) 37 | { 38 | std::random_device randomNumberDevice; 39 | std::mt19937 randomNumberEngine(randomNumberDevice()); 40 | std::uniform_int_distribution randomNumberDistribution(' ', '~'); // ASCII range for printable characters (32-126). 41 | 42 | std::string result(length, '\0'); 43 | std::ranges::generate_n(std::begin(result), static_cast(length), [&]() { 44 | return static_cast(randomNumberDistribution(randomNumberEngine)); 45 | }); 46 | 47 | return result; 48 | } 49 | } // namespace Strings 50 | -------------------------------------------------------------------------------- /src/common/shared/strings/include/strings/StringParsing.hxx: -------------------------------------------------------------------------------- 1 | 2 | #ifndef STRING_PARSING_HXX 3 | #define STRING_PARSING_HXX 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | namespace Strings 14 | { 15 | /** 16 | * @brief Parse a hex string into a container of bytes. 17 | * 18 | * @tparam ContainerT The container type to store the parsed bytes. 19 | * @param hexString The hex string to parse. 20 | * @param result The container to store the parsed bytes. 21 | * @param numberOfBytesToParse The number of bytes to parse from the hex string. 22 | * @return true If a valid hex string was parsed into the container. 23 | * @return false If the hex string was invalid or the container was too small to store the parsed bytes. 24 | */ 25 | // clang-format off 26 | template 27 | requires std::same_as, std::uint8_t> 28 | // clang-format on 29 | bool 30 | ParseHexString(const std::string& hexString, ContainerT& result, std::size_t numberOfBytesToParse = std::tuple_size_v) 31 | { 32 | // Ensure the input has enough characters to parse the requested number of bytes. 33 | if (std::size(hexString) / 2 < numberOfBytesToParse) { 34 | return false; 35 | } 36 | 37 | std::string_view hexStringView{ hexString }; 38 | for (std::size_t i = 0; i < std::size(result); i++) { 39 | const auto byteAsHex = hexStringView.substr(i * 2, 2); // 2 hex chars 40 | const auto byteConversionResult = std::from_chars(std::data(byteAsHex), std::data(byteAsHex) + std::size(byteAsHex), result[i], 16); 41 | if (byteConversionResult.ec != std::errc{}) { 42 | return false; 43 | } 44 | } 45 | 46 | return true; 47 | } 48 | } // namespace Strings 49 | 50 | #endif // STRING_PARSING_HXX 51 | -------------------------------------------------------------------------------- /src/common/tools/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_subdirectory(cli) 3 | -------------------------------------------------------------------------------- /src/common/tools/cli/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_library(${PROJECT_NAME}-cli STATIC "") 3 | 4 | set(NETREMOTE_CLI_PUBLIC_INCLUDE ${CMAKE_CURRENT_LIST_DIR}/include) 5 | set(NETREMOTE_CLI_PUBLIC_INCLUDE_SUFFIX microsoft/net/remote) 6 | set(NETREMOTE_CLI_PUBLIC_INCLUDE_PREFIX ${NETREMOTE_CLI_PUBLIC_INCLUDE}/${NETREMOTE_CLI_PUBLIC_INCLUDE_SUFFIX}) 7 | 8 | target_sources(${PROJECT_NAME}-cli 9 | PRIVATE 10 | NetRemoteCli.cxx 11 | NetRemoteCliHandler.cxx 12 | NetRemoteCliHandlerOperations.cxx 13 | PUBLIC 14 | FILE_SET HEADERS 15 | BASE_DIRS ${NETREMOTE_CLI_PUBLIC_INCLUDE} 16 | FILES 17 | ${NETREMOTE_CLI_PUBLIC_INCLUDE_PREFIX}/INetRemoteCliHandlerOperations.hxx 18 | ${NETREMOTE_CLI_PUBLIC_INCLUDE_PREFIX}/NetRemoteCli.hxx 19 | ${NETREMOTE_CLI_PUBLIC_INCLUDE_PREFIX}/NetRemoteCliData.hxx 20 | ${NETREMOTE_CLI_PUBLIC_INCLUDE_PREFIX}/NetRemoteCliHandler.hxx 21 | ${NETREMOTE_CLI_PUBLIC_INCLUDE_PREFIX}/NetRemoteCliHandlerOperations.hxx 22 | ) 23 | 24 | target_link_libraries(${PROJECT_NAME}-cli 25 | PRIVATE 26 | CLI11::CLI11 27 | magic_enum::magic_enum 28 | notstd 29 | plog::plog 30 | strings 31 | PUBLIC 32 | ${PROJECT_NAME}-client 33 | wifi-core 34 | wifi-core-adapter-dot11 35 | ) 36 | 37 | install( 38 | TARGETS ${PROJECT_NAME}-cli 39 | EXPORT ${PROJECT_NAME} 40 | COMPONENT dev 41 | FILE_SET HEADERS 42 | PUBLIC_HEADER DESTINATION "${NETREMOTE_DIR_INSTALL_PUBLIC_HEADER_BASE}/${NETREMOTE_CLI_PUBLIC_INCLUDE_SUFFIX}" 43 | ) 44 | -------------------------------------------------------------------------------- /src/common/tools/cli/include/microsoft/net/remote/NetRemoteCliData.hxx: -------------------------------------------------------------------------------- 1 | 2 | #ifndef NET_REMOTE_CLI_DATA_HXX 3 | #define NET_REMOTE_CLI_DATA_HXX 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | namespace Microsoft::Net::Remote 15 | { 16 | struct NetRemoteCli; 17 | 18 | /** 19 | * @brief Data associated with the NetRemote CLI. This is used to store command-line arguments and other data associated 20 | * with CLI configuration and operation. 21 | */ 22 | struct NetRemoteCliData 23 | { 24 | std::string ServerAddress{ Protocol::NetRemoteProtocol::AddressDefault }; 25 | std::optional DetailedOutput; 26 | 27 | std::string WifiAccessPointId{}; 28 | std::string WifiAccessPointSsid{}; 29 | std::string WifiAccessPointPskPassphrase; 30 | std::string WifiAccessPointPskHex; 31 | std::vector, std::optional>> WifiAccessPointSaePasswords{}; 32 | std::vector WifiAccessPointFrequencyBands{}; 33 | std::vector WifiAccessPointAuthenticationAlgorithms{}; 34 | std::vector WifiAccessPointAkmSuites{}; 35 | Microsoft::Net::Wifi::Ieee80211PhyType WifiAccessPointPhyType{ Microsoft::Net::Wifi::Ieee80211PhyType::Unknown }; 36 | Microsoft::Net::Wifi::Ieee80211Authentication8021x WifiAccessPointAuthentication8021x{}; 37 | }; 38 | } // namespace Microsoft::Net::Remote 39 | 40 | #endif // NET_REMOTE_CLI_DATA_HXX 41 | -------------------------------------------------------------------------------- /src/linux/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | find_package(sdbus-c++ REQUIRED) 3 | 4 | # The d-bus vcpkg port fails to export the libsystemd dependency properly via an imported target which causes the build 5 | # to fail. This is a workaround to fix that by finding the libsystemd dependency via pkg-config and defining a global 6 | # imported target. 7 | include(FindPkgConfig) 8 | pkg_check_modules(Systemd REQUIRED IMPORTED_TARGET GLOBAL libsystemd) 9 | 10 | add_subdirectory(external) 11 | add_subdirectory(libnl-helpers) 12 | add_subdirectory(net) 13 | 14 | if (NOT NETREMOTE_EXCLUDE_TOOLS) 15 | add_subdirectory(tools) 16 | endif() 17 | 18 | if (NOT NETREMOTE_EXCLUDE_SERVER) 19 | add_subdirectory(server) 20 | add_subdirectory(rfattenuator) 21 | endif() 22 | -------------------------------------------------------------------------------- /src/linux/external/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_subdirectory(hostap) 3 | add_subdirectory(libnl) 4 | -------------------------------------------------------------------------------- /src/linux/external/hostap/libwpa_client/.config: -------------------------------------------------------------------------------- 1 | # Select control interface backend for external programs, e.g, wpa_cli: 2 | # unix = UNIX domain sockets (default for Linux/*BSD) 3 | # udp = UDP sockets using localhost (127.0.0.1) 4 | # udp6 = UDP IPv6 sockets using localhost (::1) 5 | # named_pipe = Windows Named Pipe (default for Windows) 6 | # udp-remote = UDP sockets with remote access (only for tests systems/purpose) 7 | # udp6-remote = UDP IPv6 sockets with remote access (only for tests purpose) 8 | # y = use default (backwards compatibility) 9 | # If this option is commented out, control interface is not included in the 10 | # build. 11 | CONFIG_CTRL_IFACE=unix 12 | 13 | # Request to build the libwpa_client.so client library. 14 | CONFIG_BUILD_WPA_CLIENT_SO=y 15 | 16 | CONFIG_NO_WPA_PASSPHRASE=n -------------------------------------------------------------------------------- /src/linux/external/hostap/systemd/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | configure_file( 3 | ${CMAKE_CURRENT_SOURCE_DIR}/hostapd-example.conf.in 4 | ${CMAKE_CURRENT_BINARY_DIR}/hostapd-example.conf 5 | ) 6 | 7 | configure_file( 8 | ${CMAKE_CURRENT_SOURCE_DIR}/hostapd@.service.in 9 | ${CMAKE_CURRENT_BINARY_DIR}/hostapd@.service 10 | @ONLY 11 | ) 12 | 13 | configure_file( 14 | ${CMAKE_CURRENT_SOURCE_DIR}/hostapd-genconfig@.service.in 15 | ${CMAKE_CURRENT_BINARY_DIR}/hostapd-genconfig@.service 16 | @ONLY 17 | ) 18 | 19 | install( 20 | FILES 21 | ${CMAKE_CURRENT_BINARY_DIR}/hostapd-example.conf 22 | DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/hostapd 23 | COMPONENT hostapd 24 | ) 25 | 26 | install( 27 | DIRECTORY 28 | DESTINATION ${CMAKE_INSTALL_RUNSTATEDIR}/hostapd 29 | COMPONENT hostapd 30 | ) 31 | 32 | install( 33 | FILES 34 | ${CMAKE_CURRENT_BINARY_DIR}/hostapd@.service 35 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/systemd/system 36 | COMPONENT hostapd 37 | ) 38 | 39 | install( 40 | FILES 41 | ${CMAKE_CURRENT_BINARY_DIR}/hostapd-genconfig@.service 42 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/systemd/system 43 | COMPONENT hostapd 44 | ) 45 | -------------------------------------------------------------------------------- /src/linux/external/hostap/systemd/hostapd-example.conf.in: -------------------------------------------------------------------------------- 1 | # Default (generated) hostapd configuration file. 2 | driver=nl80211 3 | ctrl_interface=${CMAKE_INSTALL_FULL_RUNSTATEDIR}/hostapd 4 | ssid= 5 | hw_mode=g 6 | channel=1 7 | auth_algs=3 8 | wpa=2 9 | wpa_passphrase=password 10 | wpa_key_mgmt=SAE 11 | rsn_pairwise=CCMP 12 | ieee80211w=2 13 | bridge=brgateway0 -------------------------------------------------------------------------------- /src/linux/external/hostap/systemd/hostapd-genconfig@.service.in: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Generate default hostapd configuration file 3 | AssertPathExists=@CMAKE_INSTALL_FULL_SYSCONFDIR@/hostapd/hostapd-example.conf 4 | ConditionPathExists=!@CMAKE_INSTALL_FULL_SYSCONFDIR@/hostapd/hostapd-%i.conf 5 | 6 | [Service] 7 | Type=oneshot 8 | RemainAfterExit=true 9 | ExecStart=/usr/bin/cp @CMAKE_INSTALL_FULL_SYSCONFDIR@/hostapd/hostapd-example.conf @CMAKE_INSTALL_FULL_SYSCONFDIR@/hostapd/hostapd-%i.conf 10 | ExecStart=/usr/bin/sed -i '/^#/d' @CMAKE_INSTALL_FULL_SYSCONFDIR@/hostapd/hostapd-%i.conf 11 | ExecStart=/usr/bin/sed -i 's/ssid=/ssid=%l-ap-%i/' @CMAKE_INSTALL_FULL_SYSCONFDIR@/hostapd/hostapd-%i.conf 12 | -------------------------------------------------------------------------------- /src/linux/external/hostap/systemd/hostapd@.service.in: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Hostapd Daemon 3 | Requires=sys-subsystem-net-devices-%i.device hostapd-genconfig@%i.service 4 | After=sys-subsystem-net-devices-%i.device hostapd-genconfig@%i.service 5 | AssertPathExists=@CMAKE_INSTALL_FULL_SYSCONFDIR@/hostapd/hostapd-%i.conf 6 | 7 | [Service] 8 | Type=simple 9 | Restart=on-failure 10 | ExecStart=@CMAKE_INSTALL_FULL_SBINDIR@/hostapd -i %i @CMAKE_INSTALL_FULL_SYSCONFDIR@/hostapd/hostapd-%i.conf 11 | 12 | [Install] 13 | WantedBy=default.target 14 | -------------------------------------------------------------------------------- /src/linux/external/libnl/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | # Requires that libnl development package is installed (libnl-3-dev on ubuntu). 3 | find_path(LIBNL_INCLUDE_DIR netlink/netlink.h 4 | PATHS 5 | /usr/include/libnl3 6 | /usr/local/include/libnl3 7 | REQUIRED 8 | ) 9 | 10 | # libnl core 11 | find_library(LIBNL_STATIC NAMES libnl-3.a REQUIRED) 12 | add_library(nl STATIC IMPORTED GLOBAL) 13 | set_target_properties(nl PROPERTIES IMPORTED_LOCATION ${LIBNL_STATIC}) 14 | set_target_properties(nl PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${LIBNL_INCLUDE_DIR}) 15 | target_include_directories(nl INTERFACE ${LIBNL_INCLUDE_DIR}) 16 | 17 | # libnl-genl 18 | find_library(LIBNL_GENL_STATIC NAMES libnl-genl-3.a REQUIRED) 19 | add_library(nl-genl STATIC IMPORTED GLOBAL) 20 | set_target_properties(nl-genl PROPERTIES IMPORTED_LOCATION ${LIBNL_GENL_STATIC}) 21 | set_target_properties(nl-genl PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${LIBNL_INCLUDE_DIR}) 22 | target_include_directories(nl-genl INTERFACE ${LIBNL_INCLUDE_DIR}) 23 | 24 | # libnl-route 25 | find_library(LIBNL_ROUTE_STATIC NAMES libnl-route-3.a REQUIRED) 26 | add_library(nl-route STATIC IMPORTED GLOBAL) 27 | set_target_properties(nl-route PROPERTIES IMPORTED_LOCATION ${LIBNL_ROUTE_STATIC}) 28 | set_target_properties(nl-route PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${LIBNL_INCLUDE_DIR}) 29 | target_include_directories(nl-route INTERFACE ${LIBNL_INCLUDE_DIR}) 30 | -------------------------------------------------------------------------------- /src/linux/libnl-helpers/Netlink80211ProtocolState.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | using namespace Microsoft::Net::Netlink::Nl80211; 14 | 15 | Nl80211ProtocolState::Nl80211ProtocolState() 16 | { 17 | using Microsoft::Net::Netlink::NetlinkSocket; 18 | 19 | // Allocate a new netlink socket. 20 | auto netlinkSocket{ NetlinkSocket::Allocate() }; 21 | 22 | // Connect the socket to the generic netlink family. 23 | const int ret = genl_connect(netlinkSocket); 24 | if (ret < 0) { 25 | throw NetlinkException::CreateLogged(-ret, "Failed to connect netlink socket for nl control"); 26 | } 27 | 28 | // Look up the nl80211 driver id. 29 | DriverId = genl_ctrl_resolve(netlinkSocket, NL80211_GENL_NAME); 30 | if (DriverId < 0) { 31 | throw NetlinkException::CreateLogged(-DriverId, "Failed to resolve nl80211 netlink id"); 32 | } 33 | 34 | // Lookup the ids for the nl80211 multicast groups. 35 | for (const auto& [multicastGroup, multicastGroupName] : Nl80211MulticastGroupNames) { 36 | const int multicastGroupId = genl_ctrl_resolve_grp(netlinkSocket, NL80211_GENL_NAME, std::data(multicastGroupName)); 37 | if (multicastGroupId < 0) { 38 | throw NetlinkException::CreateLogged(-multicastGroupId, std::format("Failed to resolve nl80211 {} multicast group id", multicastGroupName)); 39 | } 40 | MulticastGroupId[multicastGroup] = multicastGroupId; 41 | } 42 | } 43 | 44 | /* static */ 45 | Nl80211ProtocolState& 46 | Nl80211ProtocolState::Instance() 47 | { 48 | static Nl80211ProtocolState protocolState; 49 | return protocolState; 50 | } 51 | -------------------------------------------------------------------------------- /src/linux/libnl-helpers/NetlinkErrorCategory.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | namespace Microsoft::Net::Netlink 10 | { 11 | 12 | const char* 13 | NetlinkErrorCategory::name() const noexcept 14 | { 15 | static constexpr const char* Name = "Netlink"; 16 | return Name; 17 | } 18 | 19 | std::string 20 | NetlinkErrorCategory::message(int error) const 21 | { 22 | return nl_geterror(error); 23 | } 24 | 25 | std::error_condition 26 | NetlinkErrorCategory::default_error_condition(int error) const noexcept 27 | { 28 | return std::error_condition(error, *this); 29 | } 30 | 31 | std::error_code 32 | make_netlink_error_code(int error) 33 | { 34 | return std::error_code(error, GetNetlinkErrorCategory()); 35 | } 36 | 37 | std::error_code 38 | MakeNetlinkErrorCode(int error) 39 | { 40 | if (error < 0) { 41 | throw std::runtime_error("Netlink error codes must be non-negative; this is a programming error"); 42 | } 43 | 44 | return make_netlink_error_code(error); 45 | } 46 | 47 | const NetlinkErrorCategory& 48 | GetNetlinkErrorCategory() 49 | { 50 | static NetlinkErrorCategory instance; 51 | return instance; 52 | } 53 | 54 | } // namespace Microsoft::Net::Netlink 55 | -------------------------------------------------------------------------------- /src/linux/libnl-helpers/NetlinkException.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace Microsoft::Net::Netlink; 11 | 12 | NetlinkException::NetlinkException(int error, const char *what) : 13 | std::system_error(MakeNetlinkErrorCode(error), what) 14 | {} 15 | 16 | NetlinkException::NetlinkException(int error, const std::string &what) : 17 | NetlinkException(error, what.c_str()) 18 | {} 19 | 20 | /* static */ 21 | NetlinkException 22 | NetlinkException::CreateLogged(int error, const char *what) 23 | { 24 | NetlinkException netlinkException(error, what); 25 | LOGE << std::format("Netlink error ({}): {} ({})", netlinkException.code().value(), netlinkException.what(), netlinkException.code().message()); 26 | return netlinkException; 27 | } 28 | 29 | /* static */ 30 | NetlinkException 31 | NetlinkException::CreateLogged(int error, const std::string &what) 32 | { 33 | return CreateLogged(error, what.c_str()); 34 | } 35 | -------------------------------------------------------------------------------- /src/linux/libnl-helpers/NetlinkMessage.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | using namespace Microsoft::Net::Netlink; 6 | 7 | /* static */ 8 | NetlinkMessage 9 | NetlinkMessage::Allocate() 10 | { 11 | auto* message = nlmsg_alloc(); 12 | return NetlinkMessage{ message }; 13 | } 14 | 15 | NetlinkMessage::NetlinkMessage(struct nl_msg* message) : 16 | Message(message) 17 | { 18 | } 19 | 20 | NetlinkMessage::NetlinkMessage(NetlinkMessage&& other) noexcept : 21 | Message(other.Message) 22 | { 23 | other.Message = nullptr; 24 | } 25 | 26 | NetlinkMessage& 27 | NetlinkMessage::operator=(NetlinkMessage&& other) noexcept 28 | { 29 | if (this != &other) { 30 | Reset(); 31 | Message = other.Message; 32 | other.Message = nullptr; 33 | } 34 | 35 | return *this; 36 | } 37 | 38 | NetlinkMessage::~NetlinkMessage() 39 | { 40 | Reset(); 41 | } 42 | 43 | void 44 | NetlinkMessage::Reset() 45 | { 46 | if (Message != nullptr) { 47 | nlmsg_free(Message); 48 | Message = nullptr; 49 | } 50 | } 51 | 52 | struct nl_msg* 53 | NetlinkMessage::Release() noexcept 54 | { 55 | auto* message = Message; 56 | Message = nullptr; 57 | return message; 58 | } 59 | 60 | NetlinkMessage::operator struct nl_msg *() const noexcept 61 | { 62 | return Message; 63 | } 64 | 65 | struct nlmsghdr* 66 | NetlinkMessage::Header() const noexcept 67 | { 68 | return nlmsg_hdr(Message); 69 | } 70 | -------------------------------------------------------------------------------- /src/linux/libnl-helpers/NetlinkSocket.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace Microsoft::Net::Netlink; 11 | 12 | /* static */ 13 | NetlinkSocket 14 | NetlinkSocket::Allocate() 15 | { 16 | auto* socket = nl_socket_alloc(); 17 | if (socket == nullptr) { 18 | throw std::system_error(MakeNetlinkErrorCode(NLE_NOMEM), "Failed to allocate netlink socket"); 19 | } 20 | 21 | return NetlinkSocket{ socket }; 22 | } 23 | 24 | NetlinkSocket::NetlinkSocket(struct nl_sock* socket) : 25 | Socket(socket) 26 | { 27 | } 28 | 29 | NetlinkSocket::NetlinkSocket(NetlinkSocket&& other) noexcept : 30 | Socket(other.Socket) 31 | { 32 | other.Socket = nullptr; 33 | } 34 | 35 | NetlinkSocket& 36 | NetlinkSocket::operator=(NetlinkSocket&& other) noexcept 37 | { 38 | if (this != &other) { 39 | Reset(); 40 | Socket = other.Socket; 41 | other.Socket = nullptr; 42 | } 43 | 44 | return *this; 45 | } 46 | 47 | NetlinkSocket::~NetlinkSocket() 48 | { 49 | Reset(); 50 | } 51 | 52 | void 53 | NetlinkSocket::Reset() noexcept 54 | { 55 | if (Socket != nullptr) { 56 | nl_socket_free(Socket); 57 | Socket = nullptr; 58 | } 59 | } 60 | 61 | struct nl_sock* 62 | NetlinkSocket::Release() noexcept 63 | { 64 | auto* socket = Socket; 65 | Socket = nullptr; 66 | return socket; 67 | } 68 | 69 | NetlinkSocket::operator struct nl_sock *() const noexcept 70 | { 71 | return Socket; 72 | } 73 | -------------------------------------------------------------------------------- /src/linux/libnl-helpers/include/microsoft/net/netlink/NetlinkException.hxx: -------------------------------------------------------------------------------- 1 | 2 | #ifndef NETLINK_EXCEPTION_HXX 3 | #define NETLINK_EXCEPTION_HXX 4 | 5 | #include 6 | #include 7 | 8 | namespace Microsoft::Net::Netlink 9 | { 10 | /** 11 | * @brief std compatible exception for Netlink errors. 12 | */ 13 | struct NetlinkException : 14 | public std::system_error 15 | { 16 | public: 17 | /** 18 | * @brief Construct a new NetlinkException object. 19 | * 20 | * @param error The netlink error code. This must be one of the NLE_* values from netlink/errno.h. 21 | * @param what The error message. 22 | */ 23 | explicit NetlinkException(int error, const char* what = ""); 24 | 25 | /** 26 | * @brief Construct a new NetlinkException object. Overload accepting a std::string. 27 | * 28 | * @param error The netlink error code. This must be one of the NLE_* values from netlink/errno.h. 29 | * @param what The error message. 30 | */ 31 | NetlinkException(int error, const std::string& what); 32 | 33 | /** 34 | * @brief Create a NetlinkException and log it. 35 | * 36 | * @param error The netlink error code. This must be one of the NLE_* values from netlink/errno.h. 37 | * @param what The error message. 38 | * @return NetlinkException 39 | */ 40 | static NetlinkException 41 | CreateLogged(int error, const char* what = ""); 42 | 43 | /** 44 | * @brief Create a NetlinkException and log it. Overload accepting a std::string. 45 | * 46 | * @param error The netlink error code. This must be one of the NLE_* values from netlink/errno.h. 47 | * @param what The error message. 48 | * @return NetlinkException 49 | */ 50 | static NetlinkException 51 | CreateLogged(int error, const std::string& what); 52 | }; 53 | 54 | /** 55 | * @brief std-style type alias for NetlinkException. 56 | */ 57 | using netlink_exception = NetlinkException; 58 | 59 | } // namespace Microsoft::Net::Netlink 60 | 61 | #endif // NETLINK_EXCEPTION_HXX 62 | -------------------------------------------------------------------------------- /src/linux/libnl-helpers/include/microsoft/net/netlink/nl80211/Netlink80211ProtocolState.hxx: -------------------------------------------------------------------------------- 1 | 2 | #ifndef NETLINK_80211_PROTOCOL_STATE_HXX 3 | #define NETLINK_80211_PROTOCOL_STATE_HXX 4 | 5 | #include 6 | 7 | #include 8 | 9 | namespace Microsoft::Net::Netlink::Nl80211 10 | { 11 | /** 12 | * @brief Dynamic state associated with the nl80211 netlink protocol. 13 | */ 14 | struct Nl80211ProtocolState 15 | { 16 | /** 17 | * @brief Driver identifier for the nl80211 protocol. 18 | */ 19 | int DriverId{ -1 }; 20 | 21 | /** 22 | * @brief Map of multicast group enum values to their ids. 23 | */ 24 | std::unordered_map MulticastGroupId; 25 | 26 | /** 27 | * @brief Return an instance of the nl80211 protocol state. 28 | * 29 | * @return Nl80211ProtocolState& 30 | */ 31 | static Nl80211ProtocolState& 32 | Instance(); 33 | 34 | private: 35 | /** 36 | * @brief Construct a new Nl80211ProtocolState object. 37 | */ 38 | Nl80211ProtocolState(); 39 | }; 40 | 41 | } // namespace Microsoft::Net::Netlink::Nl80211 42 | 43 | #endif // NETLINK_80211_PROTOCOL_STATE_HXX 44 | -------------------------------------------------------------------------------- /src/linux/libnl-helpers/include/microsoft/net/netlink/nl80211/Netlink80211WiphyBandFrequency.hxx: -------------------------------------------------------------------------------- 1 | 2 | #ifndef NETLINK_80211_WIPHY_BAND_FREQUENCY_HXX 3 | #define NETLINK_80211_WIPHY_BAND_FREQUENCY_HXX 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | namespace Microsoft::Net::Netlink::Nl80211 14 | { 15 | /** 16 | * @brief Represents information about a frequency in a netlink 802.11 wiphy radio band. 17 | */ 18 | struct WiphyBandFrequency 19 | { 20 | uint32_t Frequency; 21 | std::optional FrequencyOffset; 22 | bool IsDisabled; 23 | 24 | /** 25 | * @brief Parses a netlink attribute into a WiphyBandFrequency. 26 | * 27 | * @param wiphyBandFrequency The netlink attribute to parse. 28 | * @return std::optional 29 | */ 30 | static std::optional 31 | Parse(struct nlattr* wiphyBandFrequency) noexcept; 32 | 33 | /** 34 | * @brief Convert the frequency to a string representation. 35 | * 36 | * @return std::string 37 | */ 38 | std::string 39 | ToString() const; 40 | 41 | private: 42 | /** 43 | * @brief Construct a new Wiphy Band Frequency object. 44 | * 45 | * @param frequency The frequency in MHz. 46 | * @param frequencyOffset The fractional portion of the frequency, if any. 47 | * @param isDisabled Whether the frequency is disabled. 48 | */ 49 | WiphyBandFrequency(uint32_t frequency, std::optional frequencyOffset, bool isDisabled) noexcept; 50 | }; 51 | } // namespace Microsoft::Net::Netlink::Nl80211 52 | 53 | #endif // NETLINK_80211_WIPHY_BAND_FREQUENCY_HXX 54 | -------------------------------------------------------------------------------- /src/linux/net/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_subdirectory(core) 3 | add_subdirectory(wifi) 4 | -------------------------------------------------------------------------------- /src/linux/net/core/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_library(${PROJECT_NAME}-net-linux STATIC "") 3 | 4 | set(NET_REMOTE_NET_LINUX_PUBLIC_INCLUDE ${CMAKE_CURRENT_LIST_DIR}/include) 5 | set(NET_REMOTE_NET_LINUX_PUBLIC_INCLUDE_SUFFIX microsoft/net) 6 | set(NET_REMOTE_NET_LINUX_PUBLIC_INCLUDE_PREFIX ${NET_REMOTE_NET_LINUX_PUBLIC_INCLUDE}/${NET_REMOTE_NET_LINUX_PUBLIC_INCLUDE_SUFFIX}) 7 | 8 | target_sources(${PROJECT_NAME}-net-linux 9 | PRIVATE 10 | NetworkOperationsLinux.cxx 11 | PUBLIC 12 | FILE_SET HEADERS 13 | BASE_DIRS ${NET_REMOTE_NET_LINUX_PUBLIC_INCLUDE} 14 | FILES 15 | ${NET_REMOTE_NET_LINUX_PUBLIC_INCLUDE_PREFIX}/NetworkOperationsLinux.hxx 16 | ) 17 | 18 | target_link_libraries(${PROJECT_NAME}-net-linux 19 | PUBLIC 20 | ${PROJECT_NAME}-net 21 | plog::plog 22 | PRIVATE 23 | libnl-helpers 24 | ) 25 | -------------------------------------------------------------------------------- /src/linux/net/wifi/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_subdirectory(apmanager) 3 | add_subdirectory(core) 4 | add_subdirectory(wpa-controller) 5 | -------------------------------------------------------------------------------- /src/linux/net/wifi/apmanager/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_library(wifi-apmanager-linux STATIC "") 3 | 4 | set(WIFI_APMANAGER_LINUX_PUBLIC_INCLUDE ${CMAKE_CURRENT_LIST_DIR}/include) 5 | set(WIFI_APMANAGER_LINUX_PUBLIC_INCLUDE_SUFFIX microsoft/net/wifi) 6 | set(WIFI_APMANAGER_LINUX_PUBLIC_INCLUDE_PREFIX ${WIFI_APMANAGER_LINUX_PUBLIC_INCLUDE}/${WIFI_APMANAGER_LINUX_PUBLIC_INCLUDE_SUFFIX}) 7 | 8 | target_sources(wifi-apmanager-linux 9 | PRIVATE 10 | AccessPointDiscoveryAgentOperationsNetlink.cxx 11 | PUBLIC 12 | FILE_SET HEADERS 13 | BASE_DIRS ${WIFI_APMANAGER_LINUX_PUBLIC_INCLUDE} 14 | FILES 15 | ${WIFI_APMANAGER_LINUX_PUBLIC_INCLUDE_PREFIX}/AccessPointDiscoveryAgentOperationsNetlink.hxx 16 | ) 17 | 18 | target_link_libraries(wifi-apmanager-linux 19 | PRIVATE 20 | nl 21 | nl-genl 22 | notstd 23 | plog::plog 24 | PUBLIC 25 | libnl-helpers 26 | wifi-apmanager 27 | wifi-core 28 | wifi-core-linux 29 | ) 30 | -------------------------------------------------------------------------------- /src/linux/net/wifi/core/AccessPointLinux.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | using Microsoft::Net::Netlink::Nl80211::Nl80211Interface; 16 | 17 | using namespace Microsoft::Net::Wifi; 18 | 19 | AccessPointLinux::AccessPointLinux(std::string_view interfaceName, std::shared_ptr accessPointControllerFactory, Nl80211Interface nl80211Interface, AccessPointAttributes attributes) : 20 | AccessPoint(interfaceName, std::move(accessPointControllerFactory), std::move(attributes)), 21 | m_nl80211Interface{ std::move(nl80211Interface) } 22 | { 23 | } 24 | 25 | Ieee80211MacAddress 26 | AccessPointLinux::GetMacAddress() const noexcept 27 | { 28 | return m_nl80211Interface.MacAddress; 29 | } 30 | 31 | std::shared_ptr 32 | AccessPointFactoryLinux::Create(std::string_view interfaceName, std::unique_ptr createArgs) 33 | { 34 | auto *createArgsLinux = dynamic_cast(createArgs.get()); 35 | if (createArgsLinux == nullptr) { 36 | throw std::runtime_error("invalid arguments passed to AccessPointFactoryLinux::Create; this is a bug!"); 37 | } 38 | 39 | return std::make_shared(interfaceName, GetControllerFactory(), std::move(createArgsLinux->Interface), std::move(createArgs->Attributes)); 40 | } 41 | 42 | AccessPointCreateArgsLinux::AccessPointCreateArgsLinux(Nl80211Interface nl80211Interface) : 43 | Interface{ std::move(nl80211Interface) } 44 | { 45 | } 46 | -------------------------------------------------------------------------------- /src/linux/net/wifi/core/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_library(wifi-core-linux STATIC "") 3 | 4 | set(WIFI_CORE_LINUX_PUBLIC_INCLUDE ${CMAKE_CURRENT_LIST_DIR}/include) 5 | set(WIFI_CORE_LINUX_PUBLIC_INCLUDE_SUFFIX microsoft/net/wifi) 6 | set(WIFI_CORE_LINUX_PUBLIC_INCLUDE_PREFIX ${WIFI_CORE_LINUX_PUBLIC_INCLUDE}/${WIFI_CORE_LINUX_PUBLIC_INCLUDE_SUFFIX}) 7 | 8 | target_sources(wifi-core-linux 9 | PRIVATE 10 | AccessPointControllerLinux.cxx 11 | AccessPointLinux.cxx 12 | Ieee80211WpaAdapters.cxx 13 | Ieee80211WpaAdapters.hxx 14 | Ieee8021xWpaAdapters.cxx 15 | Ieee8021xWpaAdapters.hxx 16 | PUBLIC 17 | FILE_SET HEADERS 18 | BASE_DIRS ${WIFI_CORE_LINUX_PUBLIC_INCLUDE} 19 | FILES 20 | ${WIFI_CORE_LINUX_PUBLIC_INCLUDE_PREFIX}/AccessPointControllerLinux.hxx 21 | ${WIFI_CORE_LINUX_PUBLIC_INCLUDE_PREFIX}/AccessPointLinux.hxx 22 | ) 23 | 24 | target_link_libraries(wifi-core-linux 25 | PRIVATE 26 | plog::plog 27 | PUBLIC 28 | ${PROJECT_NAME}-net 29 | libnl-helpers 30 | logging-utils 31 | wifi-core 32 | wpa-controller 33 | ) 34 | -------------------------------------------------------------------------------- /src/linux/net/wifi/core/Ieee8021xWpaAdapters.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include "Ieee8021xWpaAdapters.hxx" 6 | 7 | namespace Microsoft::Net::Wifi 8 | { 9 | Wpa::RadiusEndpointConfiguration 10 | Ieee8021xRadiusServerEndpointConfigurationToWpaRadiusEndpointConfiguration(const Ieee8021xRadiusServerEndpointConfiguration& ieee8021xRadiusServerEndpointConfiguration) noexcept 11 | { 12 | Wpa::RadiusEndpointConfiguration wpaRadiusEndpointConfiguration{ 13 | .Type = Ieee8021xRadiusEndpointTypeToWpaRadiusEndpointType(ieee8021xRadiusServerEndpointConfiguration.Type), 14 | .Address = ieee8021xRadiusServerEndpointConfiguration.Address, 15 | .Port = ieee8021xRadiusServerEndpointConfiguration.Port, 16 | .SharedSecret = { 17 | std::cbegin(ieee8021xRadiusServerEndpointConfiguration.SharedSecret), 18 | std::cend(ieee8021xRadiusServerEndpointConfiguration.SharedSecret) }, 19 | }; 20 | 21 | return wpaRadiusEndpointConfiguration; 22 | } 23 | } // namespace Microsoft::Net::Wifi 24 | -------------------------------------------------------------------------------- /src/linux/net/wifi/core/Ieee8021xWpaAdapters.hxx: -------------------------------------------------------------------------------- 1 | 2 | #ifndef IEEE_8021X_WPA_ADAPTERS_HXX 3 | #define IEEE_8021X_WPA_ADAPTERS_HXX 4 | 5 | #include 6 | #include 7 | 8 | namespace Microsoft::Net::Wifi 9 | { 10 | /** 11 | * @brief Convert a Ieee8021xRadiusServerEndpointType to a Wpa::RadiusEndpointType. 12 | * 13 | * @param ieee8021xRadiusServerEndpointType The Ieee8021xRadiusServerEndpointType to convert. 14 | * @return constexpr Wpa::RadiusEndpointType The corresponding Wpa::RadiusEndpointType. 15 | */ 16 | constexpr Wpa::RadiusEndpointType 17 | Ieee8021xRadiusEndpointTypeToWpaRadiusEndpointType(Ieee8021xRadiusServerEndpointType ieee8021xRadiusServerEndpointType) noexcept 18 | { 19 | switch (ieee8021xRadiusServerEndpointType) { 20 | case Ieee8021xRadiusServerEndpointType::Authentication: 21 | return Wpa::RadiusEndpointType::Authentication; 22 | case Ieee8021xRadiusServerEndpointType::Accounting: 23 | return Wpa::RadiusEndpointType::Accounting; 24 | case Ieee8021xRadiusServerEndpointType::Unknown: 25 | [[fallthrough]]; 26 | default: 27 | return Wpa::RadiusEndpointType::Unknown; 28 | } 29 | } 30 | 31 | /** 32 | * @brief Convert a Ieee8021xRadiusServerEndpointConfiguration to a Wpa::RadiusEndpointConfiguration. 33 | * 34 | * @param ieee8021xRadiusServerEndpointConfiguration The Ieee8021xRadiusServerEndpointConfiguration to convert. 35 | * @return Wpa::RadiusEndpointConfiguration The corresponding Wpa::RadiusEndpointConfiguration. 36 | */ 37 | Wpa::RadiusEndpointConfiguration 38 | Ieee8021xRadiusServerEndpointConfigurationToWpaRadiusEndpointConfiguration(const Ieee8021xRadiusServerEndpointConfiguration& ieee8021xRadiusServerEndpointConfiguration) noexcept; 39 | } // namespace Microsoft::Net::Wifi 40 | 41 | #endif // IEEE_8021X_WPA_ADAPTERS_HXX 42 | -------------------------------------------------------------------------------- /src/linux/net/wifi/wpa-controller/HostapdException.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #include 5 | 6 | using namespace Wpa; 7 | 8 | HostapdException::HostapdException(std::string_view message) : 9 | m_message(message) 10 | { 11 | } 12 | 13 | const char* 14 | HostapdException::what() const noexcept 15 | { 16 | return m_message.c_str(); 17 | } 18 | -------------------------------------------------------------------------------- /src/linux/net/wifi/wpa-controller/ProtocolWpa.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #include 5 | 6 | using namespace Wpa; 7 | 8 | /* static */ 9 | bool 10 | ProtocolWpa::IsResponseOk(std::string_view response) 11 | { 12 | return (response.starts_with(ResponsePayloadOk)); 13 | } 14 | 15 | /* static */ 16 | bool 17 | ProtocolWpa::IsResponseFail(std::string_view response) 18 | { 19 | return (response.starts_with(ResponsePayloadFail)); 20 | } 21 | -------------------------------------------------------------------------------- /src/linux/net/wifi/wpa-controller/WpaCommand.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace Wpa; 10 | 11 | void 12 | WpaCommand::SetPayload(std::string_view payload) 13 | { 14 | m_payload = payload; 15 | } 16 | 17 | std::string_view 18 | WpaCommand::GetPayload() const noexcept 19 | { 20 | return m_payload; 21 | } 22 | 23 | std::shared_ptr 24 | WpaCommand::ParseResponse(std::string_view responsePayload) const 25 | { 26 | std::shared_ptr response; 27 | 28 | auto parser = CreateResponseParser(this, responsePayload); 29 | if (parser != nullptr) { 30 | response = parser->Parse(); 31 | } else { 32 | response = std::make_shared(responsePayload); 33 | } 34 | 35 | return response; 36 | } 37 | 38 | std::unique_ptr 39 | WpaCommand::CreateResponseParser([[maybe_unused]] const WpaCommand* command, [[maybe_unused]] std::string_view responsePayload) const 40 | { 41 | // Basic commands don't need a response parser since they only provide OK/FAIL results. 42 | return nullptr; 43 | } 44 | -------------------------------------------------------------------------------- /src/linux/net/wifi/wpa-controller/WpaCommandGet.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | using namespace Wpa; 9 | 10 | WpaCommandGet::WpaCommandGet(std::string_view propertyName) : 11 | PropertyPayload(std::format("{} {}", ProtocolWpa::CommandPayloadGet, propertyName)), 12 | PropertyName(propertyName) 13 | { 14 | SetPayload(PropertyPayload); 15 | } 16 | -------------------------------------------------------------------------------- /src/linux/net/wifi/wpa-controller/WpaCommandSet.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace Wpa; 10 | 11 | WpaCommandSet::WpaCommandSet(std::string_view propertyName, std::string_view propertyValue) : 12 | PropertyPayload(std::format("{} {} {}", ProtocolWpa::CommandPayloadSet, propertyName, propertyValue)), 13 | PropertyName(propertyName), 14 | PropertyValue(propertyValue) 15 | { 16 | SetPayload(PropertyPayload); 17 | } 18 | -------------------------------------------------------------------------------- /src/linux/net/wifi/wpa-controller/WpaControlSocket.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | using namespace Wpa; 10 | 11 | /* static */ 12 | bool 13 | WpaControlSocket::Exists(std::string_view interfaceName, std::filesystem::path controlSocketPath) noexcept 14 | { 15 | // Attempt to create a control socket connection to the specified path and interface. If it succeeds, the path is 16 | // valid. There's no real way around this without trying to connect to the control socket since calling open() on it 17 | // will fail even if the socket is valid and accessible. 18 | const auto wpaControlSocketConnection = WpaControlSocketConnection::TryCreate(interfaceName, std::move(controlSocketPath)); 19 | return wpaControlSocketConnection != nullptr; 20 | } 21 | 22 | /* static */ 23 | bool 24 | WpaControlSocket::Exists(std::string_view interfaceName, WpaType wpaType) noexcept 25 | { 26 | return Exists(interfaceName, DefaultPath(wpaType)); 27 | } 28 | -------------------------------------------------------------------------------- /src/linux/net/wifi/wpa-controller/WpaEventListenerProxy.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace Wpa; 9 | 10 | WpaEventListenerProxy::WpaEventListenerProxy(IWpaEventListener &wpaEventListenerProxy) : 11 | m_wpaEventListenerProxy(wpaEventListenerProxy) 12 | { 13 | } 14 | 15 | /* static */ 16 | std::shared_ptr 17 | WpaEventListenerProxy::Create(IWpaEventListener &wpaEventListenerProxy) 18 | { 19 | return std::make_shared>(wpaEventListenerProxy); 20 | } 21 | 22 | void 23 | WpaEventListenerProxy::OnWpaEvent(WpaEventSender *sender, const WpaEventArgs *eventArgs) 24 | { 25 | m_wpaEventListenerProxy.OnWpaEvent(sender, eventArgs); 26 | } 27 | -------------------------------------------------------------------------------- /src/linux/net/wifi/wpa-controller/WpaKeyValuePair.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | using namespace Wpa; 11 | -------------------------------------------------------------------------------- /src/linux/net/wifi/wpa-controller/WpaParsingUtilities.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include "WpaParsingUtilities.hxx" 11 | 12 | namespace Wpa::Parsing 13 | { 14 | bool 15 | ParseInt(std::string_view value, int& valueInt) noexcept 16 | { 17 | const auto [ptr, ec] = std::from_chars(std::data(value), std::data(value) + std::size(value), valueInt); 18 | if (ec != std::errc() || ptr != std::data(value) + std::size(value)) { 19 | LOGE << std::format("Failed to parse integer value: '{}'", value); 20 | return false; 21 | } 22 | 23 | return true; 24 | } 25 | } // namespace Wpa::Parsing 26 | -------------------------------------------------------------------------------- /src/linux/net/wifi/wpa-controller/WpaParsingUtilities.hxx: -------------------------------------------------------------------------------- 1 | 2 | #ifndef WPA_PARSING_UTILITIES_HXX 3 | #define WPA_PARSING_UTILITIES_HXX 4 | 5 | #include 6 | 7 | namespace Wpa::Parsing 8 | { 9 | /** 10 | * @brief Parse a string into an integer. 11 | * 12 | * @param value The string to parse. 13 | * @param valueInt The integer to store the result in. 14 | * @return true 15 | * @return false 16 | */ 17 | bool 18 | ParseInt(std::string_view value, int& valueInt) noexcept; 19 | 20 | } // namespace Wpa::Parsing 21 | 22 | #endif // WPA_PARSING_UTILITIES_HXX 23 | -------------------------------------------------------------------------------- /src/linux/net/wifi/wpa-controller/WpaResponse.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | using namespace Wpa; 8 | 9 | WpaResponse::WpaResponse(std::string_view payload) : 10 | m_payload(payload) 11 | { 12 | } 13 | 14 | WpaResponse::operator bool() const 15 | { 16 | return IsOk(); 17 | } 18 | 19 | bool 20 | WpaResponse::IsOk() const 21 | { 22 | return (ProtocolWpa::IsResponseOk(Payload())); 23 | } 24 | 25 | bool 26 | WpaResponse::Failed() const 27 | { 28 | return (ProtocolWpa::IsResponseFail(Payload())); 29 | } 30 | 31 | std::string_view 32 | WpaResponse::Payload() const 33 | { 34 | return m_payload; 35 | } 36 | -------------------------------------------------------------------------------- /src/linux/net/wifi/wpa-controller/include/Wpa/IWpaEventListener.hxx: -------------------------------------------------------------------------------- 1 | 2 | #ifndef I_WPA_EVENT_HANDLER_HXX 3 | #define I_WPA_EVENT_HANDLER_HXX 4 | 5 | #include 6 | 7 | namespace Wpa 8 | { 9 | /** 10 | * @brief Represents the sender or source of a WPA event. 11 | */ 12 | struct WpaEventSender 13 | { 14 | virtual ~WpaEventSender() = default; 15 | }; 16 | 17 | /** 18 | * @brief Interface for WPA event consumers. 19 | */ 20 | struct IWpaEventListener 21 | { 22 | virtual ~IWpaEventListener() = default; 23 | 24 | /** 25 | * @brief Invoked when a WPA event is received. 26 | * 27 | * @param sender The sender or source of the event. 28 | * @param eventArgs The event arguments. 29 | */ 30 | virtual void 31 | OnWpaEvent(WpaEventSender *sender, const WpaEventArgs *eventArgs) = 0; 32 | }; 33 | } // namespace Wpa 34 | 35 | #endif // I_WPA_EVENT_HANDLER_HXX 36 | -------------------------------------------------------------------------------- /src/linux/net/wifi/wpa-controller/include/Wpa/ProtocolWpaConfig.hxx: -------------------------------------------------------------------------------- 1 | 2 | #ifndef PROTOCOL_WPA_CONFIG_HXX 3 | #define PROTOCOL_WPA_CONFIG_HXX 4 | 5 | #ifndef CONFIG_WPA_CONTROL_SOCKET_PATH_BASE 6 | #error "CONFIG_WPA_CONTROL_SOCKET_PATH_BASE must be defined." 7 | #endif 8 | 9 | #include 10 | 11 | namespace Wpa 12 | { 13 | /** 14 | * @brief Generic WPA configuration values that depend on build settings. 15 | * 16 | * Note that this is a generated file. 17 | */ 18 | struct ProtocolWpaConfig 19 | { 20 | /** 21 | * @brief The common base (parent) path used for all WPA control sockets. 22 | */ 23 | static constexpr auto ControlSocketPathBase{ CONFIG_WPA_CONTROL_SOCKET_PATH_BASE }; 24 | 25 | /** 26 | * @brief The path to the control sockets used by wpa_supplicant. 27 | */ 28 | static constexpr auto ControlSocketPathWpaSupplicant{ CONFIG_WPA_CONTROL_SOCKET_PATH_BASE "/wpa_supplicant" }; 29 | 30 | /** 31 | * @brief The path to the control sockets used by hostapd. 32 | */ 33 | static constexpr auto ControlSocketPathHostapd{ CONFIG_WPA_CONTROL_SOCKET_PATH_BASE "/hostapd" }; 34 | 35 | /** 36 | * @brief Get the control socket path for the specified WPA type. 37 | * 38 | * @param wpaType The type of WPA daemon to get the control socket path for. 39 | * @return constexpr auto The control socket path for the specified WPA type. 40 | */ 41 | static constexpr auto 42 | GetControlSocketPath(WpaType wpaType) 43 | { 44 | switch (wpaType) { 45 | case WpaType::Hostapd: 46 | return ControlSocketPathHostapd; 47 | case WpaType::WpaSupplicant: 48 | return ControlSocketPathWpaSupplicant; 49 | case WpaType::Unknown: 50 | [[fallthrough]]; 51 | default: 52 | return ControlSocketPathBase; 53 | } 54 | } 55 | }; 56 | } // namespace Wpa 57 | 58 | #undef CONFIG_WPA_CONTROL_SOCKET_PATH_BASE 59 | 60 | #endif // PROTOCOL_WPA_CONFIG_HXX 61 | -------------------------------------------------------------------------------- /src/linux/net/wifi/wpa-controller/include/Wpa/WpaCommandGet.hxx: -------------------------------------------------------------------------------- 1 | 2 | #ifndef WPA_COMMAND_GET_HXX 3 | #define WPA_COMMAND_GET_HXX 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | namespace Wpa 11 | { 12 | /** 13 | * @brief Representation of the "GET" command. 14 | */ 15 | struct WpaCommandGet : 16 | public WpaCommand 17 | { 18 | /** 19 | * @brief Construct a new WpaCommandGet object for the specified property. 20 | * 21 | * @param propertyName The name of the property to retrieve. 22 | */ 23 | explicit WpaCommandGet(std::string_view propertyName); 24 | 25 | std::string PropertyPayload; 26 | std::string_view PropertyName; 27 | }; 28 | 29 | } // namespace Wpa 30 | 31 | #endif // WPA_COMMAND_GET_HXX 32 | -------------------------------------------------------------------------------- /src/linux/net/wifi/wpa-controller/include/Wpa/WpaCommandGetConfig.hxx: -------------------------------------------------------------------------------- 1 | 2 | #ifndef WPA_COMMAND_GET_CONFIG_HXX 3 | #define WPA_COMMAND_GET_CONFIG_HXX 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | namespace Wpa 12 | { 13 | /** 14 | * @brief Representation of the "GET_CONFIG" command. 15 | */ 16 | struct WpaCommandGetConfig : 17 | public WpaCommand 18 | { 19 | /** 20 | * @brief Construct a new WpaCommandGetConfig object. 21 | */ 22 | constexpr WpaCommandGetConfig() : 23 | WpaCommand(ProtocolWpa::CommandPayloadGetConfig) 24 | { 25 | } 26 | 27 | private: 28 | /** 29 | * @brief Create a WpaResponseParser object that is specific to the "GET_CONFIG" command. 30 | * 31 | * @param command 32 | * @param responsePayload 33 | * @return std::unique_ptr 34 | */ 35 | std::unique_ptr 36 | CreateResponseParser(const WpaCommand* command, std::string_view responsePayload) const override; 37 | }; 38 | 39 | /** 40 | * @brief Parser for the "GET_CONFIG" command response. 41 | */ 42 | struct WpaGetConfigResponseParser : 43 | public WpaResponseParser 44 | { 45 | /** 46 | * @brief Construct a new WpaGetConfigResponseParser object. 47 | * 48 | * @param command The command associated with the response. 49 | * @param responsePayload The response payload to parse. 50 | */ 51 | WpaGetConfigResponseParser(const WpaCommand* command, std::string_view responsePayload); 52 | 53 | /** 54 | * @brief Parses the response payload, returning a WpaResponseStatus object 55 | * if successful. 56 | * 57 | * @return std::shared_ptr 58 | */ 59 | std::shared_ptr 60 | ParsePayload() override; 61 | }; 62 | 63 | } // namespace Wpa 64 | 65 | #endif // WPA_COMMAND_GET_CONFIG_HXX 66 | -------------------------------------------------------------------------------- /src/linux/net/wifi/wpa-controller/include/Wpa/WpaCommandSet.hxx: -------------------------------------------------------------------------------- 1 | 2 | #ifndef WPA_COMMAND_SET_HXX 3 | #define WPA_COMMAND_SET_HXX 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | namespace Wpa 11 | { 12 | /** 13 | * @brief Representation of the "SET" command. 14 | */ 15 | struct WpaCommandSet : 16 | public WpaCommand 17 | { 18 | /** 19 | * @brief Construct a new WpaCommandSet object for the specified property. 20 | * 21 | * @param propertyName The name of the property to set. 22 | * @param propertyValue The value to set the property to. 23 | */ 24 | WpaCommandSet(std::string_view propertyName, std::string_view propertyValue); 25 | 26 | std::string PropertyPayload; 27 | std::string_view PropertyName; 28 | std::string_view PropertyValue; 29 | }; 30 | 31 | } // namespace Wpa 32 | 33 | #endif // WPA_COMMAND_SET_HXX 34 | -------------------------------------------------------------------------------- /src/linux/net/wifi/wpa-controller/include/Wpa/WpaCommandStatus.hxx: -------------------------------------------------------------------------------- 1 | 2 | #ifndef WPA_COMMAND_STATUS_HXX 3 | #define WPA_COMMAND_STATUS_HXX 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | namespace Wpa 12 | { 13 | /** 14 | * @brief Representation of the "STATUS" command. 15 | */ 16 | struct WpaCommandStatus : 17 | public WpaCommand 18 | { 19 | /** 20 | * @brief Construct a new WpaCommandStatus object. 21 | */ 22 | constexpr WpaCommandStatus() : 23 | WpaCommand(ProtocolWpa::CommandPayloadStatus) 24 | { 25 | } 26 | 27 | private: 28 | std::unique_ptr 29 | CreateResponseParser(const WpaCommand* command, std::string_view responsePayload) const override; 30 | }; 31 | 32 | /** 33 | * @brief Parser for the "STATUS" command response. 34 | */ 35 | struct WpaStatusResponseParser : 36 | public WpaResponseParser 37 | { 38 | /** 39 | * @brief Construct a new WpaStatusResponseParser object. 40 | * 41 | * @param command The command associated with the response. 42 | * @param responsePayload The response payload to parse. 43 | */ 44 | WpaStatusResponseParser(const WpaCommand* command, std::string_view responsePayload); 45 | 46 | /** 47 | * @brief Parses the response payload, returning a WpaResponseStatus object 48 | * if successful. 49 | * 50 | * @return std::shared_ptr 51 | */ 52 | std::shared_ptr 53 | ParsePayload() override; 54 | }; 55 | 56 | } // namespace Wpa 57 | 58 | #endif // WPA_COMMAND_STATUS_HXX 59 | -------------------------------------------------------------------------------- /src/linux/net/wifi/wpa-controller/include/Wpa/WpaCore.hxx: -------------------------------------------------------------------------------- 1 | 2 | #ifndef WPA_CORE_HXX 3 | #define WPA_CORE_HXX 4 | 5 | #include 6 | 7 | namespace Wpa 8 | { 9 | /** 10 | * @brief Log levels for WPA messages and events. 11 | */ 12 | enum class WpaLogLevel : int32_t { 13 | Unknown = -1, 14 | Excessive = 0, 15 | MessageDump = 1, 16 | Debug = 2, 17 | Info = 3, 18 | Warning = 4, 19 | Error = 5, 20 | }; 21 | 22 | /** 23 | * @brief The type of WPA daemon/service. 24 | */ 25 | enum class WpaType { 26 | Unknown, 27 | Hostapd, 28 | WpaSupplicant, 29 | }; 30 | 31 | /** 32 | * @brief Get the WpaType associated daemon binary name. 33 | * 34 | * @param type The WpaType to obtain the daemon binary name for. 35 | * @return std::string_view 36 | */ 37 | static constexpr std::string_view 38 | GetWpaTypeDaemonBinaryName(WpaType type) noexcept 39 | { 40 | switch (type) { 41 | case WpaType::Hostapd: 42 | return "hostapd"; 43 | case WpaType::WpaSupplicant: 44 | return "wpa_supplicant"; 45 | case WpaType::Unknown: 46 | [[fallthrough]]; 47 | default: 48 | return "unknown"; 49 | } 50 | } 51 | 52 | } // namespace Wpa 53 | 54 | #endif // WPA_CORE_HXX 55 | -------------------------------------------------------------------------------- /src/linux/net/wifi/wpa-controller/include/Wpa/WpaEvent.hxx: -------------------------------------------------------------------------------- 1 | 2 | #ifndef WPA_EVENT_HXX 3 | #define WPA_EVENT_HXX 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | namespace Wpa 12 | { 13 | /** 14 | * @brief Represents an event from a WPA daemon/service. 15 | */ 16 | struct WpaEvent 17 | { 18 | WpaType Source{ WpaType::Unknown }; 19 | WpaLogLevel LogLevel{ WpaLogLevel::Unknown }; 20 | std::string Payload{}; 21 | std::optional Interface{ std::nullopt }; 22 | 23 | /** 24 | * @brief Parse a string into a WpaEvent. 25 | * 26 | * @param eventPayload The string to parse. 27 | * @return std::optional 28 | */ 29 | static std::optional 30 | Parse(std::string_view eventPayload); 31 | 32 | /** 33 | * @brief Convert the event to a string. 34 | * 35 | * @return std::string 36 | */ 37 | std::string 38 | ToString() const; 39 | }; 40 | 41 | } // namespace Wpa 42 | 43 | #endif // WPA_EVENT_HXX 44 | -------------------------------------------------------------------------------- /src/linux/net/wifi/wpa-controller/include/Wpa/WpaEventArgs.hxx: -------------------------------------------------------------------------------- 1 | 2 | #ifndef WPA_EVENT_ARGS_HXX 3 | #define WPA_EVENT_ARGS_HXX 4 | 5 | #include 6 | 7 | #include 8 | 9 | namespace Wpa 10 | { 11 | /** 12 | * @brief The event arguments for the WPA event. 13 | */ 14 | struct WpaEventArgs 15 | { 16 | std::chrono::time_point Timestamp; 17 | WpaEvent Event; 18 | }; 19 | } // namespace Wpa 20 | 21 | #endif // WPA_EVENT_ARGS_HXX 22 | -------------------------------------------------------------------------------- /src/linux/net/wifi/wpa-controller/include/Wpa/WpaKeyValuePair.hxx: -------------------------------------------------------------------------------- 1 | 2 | #ifndef WPA_KEY_VALUE_PAIR_HXX 3 | #define WPA_KEY_VALUE_PAIR_HXX 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | namespace Wpa 12 | { 13 | /** 14 | * @brief Describes the presence of a property in a WPA control protocol 15 | * response. 16 | */ 17 | enum class WpaValuePresence : bool { 18 | Required = true, 19 | Optional = false, 20 | }; 21 | 22 | /** 23 | * @brief Represents a key-value pair in the WPA control protocol. Most commands 24 | * output lists of data as key-value pairs with a '=' delimiter. 25 | * 26 | * This class helps parse and collect such pairs. 27 | */ 28 | struct WpaKeyValuePair 29 | { 30 | /** 31 | * @brief The delimeter separating keys from values. 32 | */ 33 | static constexpr auto KeyDelimiter = ProtocolWpa::KeyValueDelimiter; 34 | 35 | /** 36 | * @brief Construct a new WpaKeyValue Pair object. 37 | * 38 | * @param key The key of the property. 39 | * @param presence Whether the property is required or optional. 40 | * @param isIndexed Whether the property is indexed (i.e. has a numeric suffix in its key name). 41 | */ 42 | constexpr WpaKeyValuePair(std::string_view key, WpaValuePresence presence, bool isIndexed = false) : 43 | Key(key), 44 | IsRequired(std::to_underlying(presence)), 45 | IsIndexed(isIndexed) 46 | { 47 | } 48 | 49 | std::string_view Key; 50 | std::optional Value; 51 | bool IsRequired{ true }; 52 | bool IsIndexed{ false }; 53 | }; 54 | } // namespace Wpa 55 | 56 | #endif // WPA_KEY_VALUE_PAIR_HXX 57 | -------------------------------------------------------------------------------- /src/linux/net/wifi/wpa-controller/include/Wpa/WpaResponseGetConfig.hxx: -------------------------------------------------------------------------------- 1 | 2 | #ifndef WPA_RESPONSE_GET_CONFIG_HXX 3 | #define WPA_RESPONSE_GET_CONFIG_HXX 4 | 5 | #include 6 | #include 7 | 8 | namespace Wpa 9 | { 10 | /** 11 | * @brief Representation of the response to the "GET_CONFIG" command. 12 | */ 13 | struct WpaResponseGetConfig : 14 | public WpaResponse 15 | { 16 | WpaResponseGetConfig() = default; 17 | 18 | HostapdBssConfiguration Configuration; 19 | }; 20 | } // namespace Wpa 21 | 22 | #endif // WPA_RESPONSE_COMMAND_GET_CONFIG_HXX 23 | -------------------------------------------------------------------------------- /src/linux/net/wifi/wpa-controller/include/Wpa/WpaResponseStatus.hxx: -------------------------------------------------------------------------------- 1 | 2 | #ifndef WPA_RESPONSE_STATUS_HXX 3 | #define WPA_RESPONSE_STATUS_HXX 4 | 5 | #include 6 | #include 7 | 8 | namespace Wpa 9 | { 10 | /** 11 | * @brief Representation of the response to the "STATUS" command. 12 | */ 13 | struct WpaResponseStatus : 14 | public WpaResponse 15 | { 16 | WpaResponseStatus() = default; 17 | 18 | HostapdStatus Status; 19 | }; 20 | } // namespace Wpa 21 | 22 | #endif // WPA_RESPONSE_COMMAND_STATUS_HXX 23 | -------------------------------------------------------------------------------- /src/linux/rfattenuator/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(lib) 2 | add_subdirectory(cli) -------------------------------------------------------------------------------- /src/linux/rfattenuator/cli/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(${PROJECT_NAME}-rfattenuator-cli-linux) 2 | 3 | target_sources(${PROJECT_NAME}-rfattenuator-cli-linux 4 | PRIVATE 5 | Main.cxx 6 | ) 7 | 8 | target_link_libraries(${PROJECT_NAME}-rfattenuator-cli-linux 9 | PRIVATE 10 | ${PROJECT_NAME}-rfattenuator-linux 11 | ) 12 | 13 | set_target_properties(${PROJECT_NAME}-rfattenuator-cli-linux 14 | PROPERTIES 15 | OUTPUT_NAME rfattenuator-cli 16 | ) -------------------------------------------------------------------------------- /src/linux/rfattenuator/lib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_library(${PROJECT_NAME}-rfattenuator-linux STATIC "") 3 | 4 | set(NET_REMOTE_RFATTENUATOR_LINUX_PUBLIC_INCLUDE ${CMAKE_CURRENT_LIST_DIR}/include) 5 | set(NET_REMOTE_RFATTENUATOR_LINUX_PUBLIC_INCLUDE_SUFFIX microsoft/net/remote/service) 6 | set(NET_REMOTE_RFATTENUATOR_LINUX_PUBLIC_INCLUDE_PREFIX ${NET_REMOTE_RFATTENUATOR_LINUX_PUBLIC_INCLUDE}/${NET_REMOTE_RFATTENUATOR_LINUX_PUBLIC_INCLUDE_SUFFIX}) 7 | 8 | target_sources(${PROJECT_NAME}-rfattenuator-linux 9 | PRIVATE 10 | RfAttenuatorAeroflexWeinschle83XX.cxx 11 | RfAttenuatorExceptionImpl.cxx 12 | RfAttenuatorFactoryImpl.cxx 13 | RfAttenuatorProtocol.cxx 14 | RfAttenuatorSoftwareSimulated.cxx 15 | RfAttenuatorTransport.cxx 16 | RfAttenuatorTransportSocketLinux.cxx 17 | SocketHelpers.cxx 18 | PUBLIC 19 | FILE_SET HEADERS 20 | BASE_DIRS ${NET_REMOTE_RFATTENUATOR_LINUX_PUBLIC_INCLUDE} 21 | FILES 22 | ${NET_REMOTE_RFATTENUATOR_LINUX_PUBLIC_INCLUDE_PREFIX}/RfAttenuatorFactory.hxx 23 | ) 24 | 25 | target_link_libraries(${PROJECT_NAME}-rfattenuator-linux 26 | PUBLIC 27 | ${PROJECT_NAME}-rfattenuator-interface 28 | PRIVATE 29 | strings 30 | ) 31 | 32 | install( 33 | TARGETS ${PROJECT_NAME}-rfattenuator-linux 34 | EXPORT ${PROJECT_NAME} 35 | COMPONENT dev 36 | FILE_SET HEADERS 37 | PUBLIC_HEADER DESTINATION "${NETREMOTE_DIR_INSTALL_PUBLIC_HEADER_BASE}/${NET_REMOTE_RFATTENUATOR_LINUX_PUBLIC_INCLUDE_SUFFIX}" 38 | ) -------------------------------------------------------------------------------- /src/linux/rfattenuator/lib/RfAttenuatorExceptionImpl.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include "RfAttenuatorExceptionImpl.hxx" 3 | 4 | RfAttenuatorExceptionImpl::RfAttenuatorExceptionImpl(std::string what) : 5 | m_what(std::move(what)) 6 | { 7 | } 8 | 9 | const char* 10 | RfAttenuatorExceptionImpl::what() const noexcept 11 | { 12 | return m_what.c_str(); 13 | } 14 | -------------------------------------------------------------------------------- /src/linux/rfattenuator/lib/RfAttenuatorExceptionImpl.hxx: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | /** 8 | * @brief Primary base implementation of RfAttenuatorException. Sub-classing of 9 | * exceptions should be done with this class as the parent. 10 | */ 11 | struct RfAttenuatorExceptionImpl : public RfAttenuatorException 12 | { 13 | virtual ~RfAttenuatorExceptionImpl() = default; 14 | RfAttenuatorExceptionImpl() = default; 15 | RfAttenuatorExceptionImpl(std::string what); 16 | 17 | const char* 18 | what() const noexcept override; 19 | 20 | private: 21 | std::string m_what{}; 22 | }; 23 | -------------------------------------------------------------------------------- /src/linux/rfattenuator/lib/RfAttenuatorTransport.cxx: -------------------------------------------------------------------------------- 1 | #include "RfAttenuatorTransport.hxx" 2 | 3 | RfAttenuatorTransportException::RfAttenuatorTransportException(std::string what) : 4 | RfAttenuatorExceptionImpl(std::move(what)) 5 | { 6 | } 7 | -------------------------------------------------------------------------------- /src/linux/rfattenuator/lib/include/microsoft/net/remote/service/RfAttenuatorFactory.hxx: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | /** 9 | * @brief Factory class for creating attenuator controller instances. 10 | */ 11 | struct RfAttenuatorFactory 12 | { 13 | /** 14 | * @brief Create a basic attenuator that does not require configuration. 15 | * 16 | * @param attenuatorName 17 | * @param properties The properties the attenuator should support. 18 | * @return std::unique_ptr 19 | */ 20 | static std::unique_ptr 21 | TryCreateBasic(std::string attenuatorName, RfAttenuatorProperties properties); 22 | 23 | /** 24 | * @brief Create an attenuator which uses TCP as the communication transport. 25 | * 26 | * @param attenuatorName The name of the attenuator. 27 | * @param args The arguments needed to establish a TCP connection with the attenuator. 28 | * @return std::unique_ptr 29 | */ 30 | static std::unique_ptr 31 | TryCreateWithTcpConnection(std::string attenuatorName, RfAttenuatorConnectionArgumentsTcp args); 32 | 33 | /** 34 | * @brief Create a simulated software attenuator. 35 | * 36 | * @return std::unique_ptr 37 | */ 38 | static std::unique_ptr 39 | CreateSimulatedSoftwareAttenuator(); 40 | 41 | /** 42 | * @brief Create a socket-based AFW83 attenuator. 43 | * 44 | * @param ipAddress The IP address of the attenuator. 45 | * @param port The port of the attenuator. 46 | * @return std::unique_ptr 47 | */ 48 | static std::unique_ptr 49 | CreateSocketAfw83Attenuator(std::string ipAddress, uint16_t port); 50 | }; 51 | -------------------------------------------------------------------------------- /src/linux/server/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_executable(${PROJECT_NAME}-server-linux "") 3 | 4 | target_sources(${PROJECT_NAME}-server-linux 5 | PRIVATE 6 | Main.cxx 7 | NetRemoteDiscoveryServiceLinuxDnssd.cxx 8 | NetRemoteDiscoveryServiceLinuxDnssd.hxx 9 | SystemdResolvedDnssd.cxx 10 | SystemdResolvedDnssd.hxx 11 | ) 12 | 13 | target_link_libraries(${PROJECT_NAME}-server-linux 14 | PRIVATE 15 | ${PROJECT_NAME}-net-linux 16 | ${PROJECT_NAME}-server 17 | ${PROJECT_NAME}-rfattenuator-linux 18 | logging-utils 19 | notstd 20 | plog::plog 21 | SDBusCpp::sdbus-c++ 22 | wifi-apmanager-linux 23 | wifi-core-linux 24 | ) 25 | 26 | set_target_properties(${PROJECT_NAME}-server-linux 27 | PROPERTIES 28 | OUTPUT_NAME ${PROJECT_NAME}-server 29 | ) 30 | 31 | install( 32 | TARGETS ${PROJECT_NAME}-server-linux 33 | DESTINATION ${CMAKE_INSTALL_BINDIR} 34 | EXPORT ${PROJECT_NAME} 35 | COMPONENT server 36 | ) 37 | 38 | add_subdirectory(systemd) 39 | -------------------------------------------------------------------------------- /src/linux/server/systemd/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | configure_file( 3 | ${CMAKE_CURRENT_SOURCE_DIR}/netremote-server.service.in 4 | ${CMAKE_CURRENT_BINARY_DIR}/netremote-server.service 5 | @ONLY 6 | ) 7 | 8 | install( 9 | FILES 10 | ${CMAKE_CURRENT_BINARY_DIR}/netremote-server.service 11 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/systemd/system 12 | COMPONENT server 13 | ) 14 | -------------------------------------------------------------------------------- /src/linux/server/systemd/drop-ins/enable-mdns-resolved-global.conf: -------------------------------------------------------------------------------- 1 | 2 | # See https://www.freedesktop.org/software/systemd/man/latest/resolved.conf.html#Description for more information. 3 | [Resolve] 4 | # Enable system-wide peer-to-peer network resolution. 5 | MulticastDNS=yes 6 | -------------------------------------------------------------------------------- /src/linux/server/systemd/drop-ins/enable-mdns.conf: -------------------------------------------------------------------------------- 1 | 2 | # See https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html#Description for more information. 3 | [Network] 4 | # Enable multicast DNS (mDNS) to allow discovery of netremote-server instances on the network. 5 | MulticastDNS=yes 6 | -------------------------------------------------------------------------------- /src/linux/server/systemd/netremote-server.service.in: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Netremote Daemon 3 | Wants=network-online.target 4 | After=network-online.target 5 | 6 | [Service] 7 | Type=simple 8 | Restart=on-failure 9 | ExecStart=@CMAKE_INSTALL_FULL_BINDIR@/netremote-server 10 | 11 | [Install] 12 | WantedBy=default.target 13 | -------------------------------------------------------------------------------- /src/linux/tools/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_subdirectory(apmonitor) 3 | add_subdirectory(cli) 4 | -------------------------------------------------------------------------------- /src/linux/tools/apmonitor/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_executable(apmonitor-cli-linux) 3 | 4 | target_sources(apmonitor-cli-linux 5 | PRIVATE 6 | Main.cxx 7 | ) 8 | 9 | target_link_libraries(apmonitor-cli-linux 10 | PRIVATE 11 | plog::plog 12 | wifi-apmanager-linux 13 | wifi-core-linux 14 | ) 15 | 16 | set_target_properties(apmonitor-cli-linux 17 | PROPERTIES 18 | OUTPUT_NAME apmonitor 19 | ) 20 | -------------------------------------------------------------------------------- /src/linux/tools/cli/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_executable(${PROJECT_NAME}-cli-linux) 3 | 4 | target_sources(${PROJECT_NAME}-cli-linux 5 | PRIVATE 6 | Main.cxx 7 | ) 8 | 9 | target_link_libraries(${PROJECT_NAME}-cli-linux 10 | PRIVATE 11 | magic_enum::magic_enum 12 | plog::plog 13 | ${PROJECT_NAME}-cli 14 | ${PROJECT_NAME}-client 15 | ) 16 | 17 | set_target_properties(${PROJECT_NAME}-cli-linux 18 | PROPERTIES 19 | OUTPUT_NAME netremote-cli 20 | ) 21 | 22 | install( 23 | TARGETS ${PROJECT_NAME}-cli-linux 24 | EXPORT ${PROJECT_NAME} 25 | COMPONENT server 26 | ) 27 | -------------------------------------------------------------------------------- /src/linux/tools/cli/Main.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | using Microsoft::Net::Remote::NetRemoteCli; 14 | using Microsoft::Net::Remote::NetRemoteCliData; 15 | using Microsoft::Net::Remote::NetRemoteCliHandler; 16 | using Microsoft::Net::Remote::NetRemoteCliHandlerOperationsFactory; 17 | 18 | int 19 | main(int argc, char *argv[]) 20 | { 21 | static plog::ColorConsoleAppender colorConsoleAppender{}; 22 | plog::init(plog::debug, &colorConsoleAppender); 23 | 24 | auto cliData = std::make_shared(); 25 | auto cliHandler = std::make_shared(std::make_unique()); 26 | auto cli{ NetRemoteCli::Create(cliData, cliHandler) }; 27 | 28 | const int ret = cli->Parse(argc, argv); 29 | if (ret != 0) { 30 | return ret; 31 | } 32 | 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /src/windows/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | # Add Windows-specific global compile definitions. 3 | add_compile_definitions( 4 | _UNICODE 5 | UNICODE 6 | NOMINMAX 7 | WIN32_LEAN_AND_MEAN 8 | ) 9 | 10 | # Allow more than default number of sections in object files. 11 | add_compile_options( 12 | /bigobj 13 | ) 14 | 15 | if (NOT NETREMOTE_EXCLUDE_SERVER) 16 | add_subdirectory(server) 17 | endif() 18 | -------------------------------------------------------------------------------- /src/windows/server/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_executable(${PROJECT_NAME}-server-windows "") 3 | 4 | target_sources(${PROJECT_NAME}-server-windows 5 | PRIVATE 6 | Main.cxx 7 | ) 8 | 9 | target_link_libraries(${PROJECT_NAME}-server-windows 10 | PRIVATE 11 | ${PROJECT_NAME}-server 12 | wifi-apmanager 13 | ) 14 | 15 | set_target_properties(${PROJECT_NAME}-server-windows 16 | PROPERTIES 17 | OUTPUT_NAME ${PROJECT_NAME}-server 18 | ) 19 | 20 | install( 21 | TARGETS ${PROJECT_NAME}-server-windows 22 | EXPORT ${PROJECT_NAME} 23 | COMPONENT server 24 | ) 25 | 26 | -------------------------------------------------------------------------------- /src/windows/server/Main.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | using namespace Microsoft::Net; 13 | using namespace Microsoft::Net::Remote; 14 | using namespace Microsoft::Net::Remote::Service; 15 | using namespace Microsoft::Net::Wifi; 16 | 17 | int 18 | main(int argc, char* argv[]) 19 | { 20 | auto configuration = NetRemoteServerConfiguration::FromCommandLineArguments(argc, argv); 21 | { 22 | auto accessPointManager = AccessPointManager::Create(); 23 | auto networkManager = std::make_shared(nullptr, accessPointManager); 24 | configuration.NetworkManager = networkManager; 25 | } 26 | 27 | NetRemoteServer server{ std::move(configuration) }; 28 | server.Run(); 29 | server.GetGrpcServer()->Wait(); 30 | 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_subdirectory(unit) 3 | -------------------------------------------------------------------------------- /tests/unit/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | find_package(Catch2 3 REQUIRED) 3 | 4 | # Allow CTest to discover Catch2 tests automatically 5 | list(APPEND CMAKE_MODULE_PATH "${catch2_SOURCE_DIR}/contrib") 6 | include(Catch) 7 | 8 | add_executable(${PROJECT_NAME}-test-unit) 9 | 10 | target_sources(${PROJECT_NAME}-test-unit 11 | PRIVATE 12 | ${CMAKE_CURRENT_LIST_DIR}/Main.cxx 13 | ${CMAKE_CURRENT_LIST_DIR}/TestNetRemoteCommon.cxx 14 | ${CMAKE_CURRENT_LIST_DIR}/TestNetRemoteServer.cxx 15 | ${CMAKE_CURRENT_LIST_DIR}/TestNetRemoteServiceClient.cxx 16 | ${CMAKE_CURRENT_LIST_DIR}/TestNetRemoteDataStreamingServiceClient.cxx 17 | ${CMAKE_CURRENT_LIST_DIR}/TestNetRemoteDataStreamingReactors.cxx 18 | ) 19 | 20 | target_link_libraries(${PROJECT_NAME}-test-unit 21 | PRIVATE 22 | ${PROJECT_NAME}-net 23 | ${PROJECT_NAME}-net-test-helpers 24 | ${PROJECT_NAME}-server 25 | Catch2::Catch2 26 | gRPC::grpc++ 27 | magic_enum::magic_enum 28 | plog::plog 29 | wifi-test-helpers 30 | ) 31 | 32 | catch_discover_tests(${PROJECT_NAME}-test-unit) 33 | 34 | add_subdirectory(net) 35 | 36 | if (BUILD_FOR_LINUX) 37 | add_subdirectory(linux) 38 | endif() 39 | -------------------------------------------------------------------------------- /tests/unit/Main.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int 9 | main(int argc, char* argv[]) 10 | { 11 | static plog::ColorConsoleAppender colorConsoleAppender{}; 12 | 13 | plog::init(plog::debug, &colorConsoleAppender); 14 | 15 | return Catch::Session().run(argc, argv); 16 | } 17 | -------------------------------------------------------------------------------- /tests/unit/linux/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_subdirectory(libnl-helpers) 3 | add_subdirectory(net) 4 | add_subdirectory(wifi) 5 | add_subdirectory(rfattenuator) 6 | -------------------------------------------------------------------------------- /tests/unit/linux/libnl-helpers/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_executable(libnl-helpers-test-unit) 3 | 4 | target_sources(libnl-helpers-test-unit 5 | PRIVATE 6 | Main.cxx 7 | TestNetlink80211Interface.cxx 8 | TestNetlink80211ProtocolState.cxx 9 | TestNetlinkException.cxx 10 | TestNetlinkRoute.cxx 11 | ) 12 | 13 | target_include_directories(libnl-helpers-test-unit 14 | PRIVATE 15 | ${CMAKE_CURRENT_SOURCE_DIR} 16 | ) 17 | 18 | target_link_libraries(libnl-helpers-test-unit 19 | PRIVATE 20 | Catch2::Catch2 21 | libnl-helpers 22 | magic_enum::magic_enum 23 | ) 24 | 25 | catch_discover_tests(libnl-helpers-test-unit) 26 | -------------------------------------------------------------------------------- /tests/unit/linux/libnl-helpers/Main.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int 9 | main(int argc, char* argv[]) 10 | { 11 | static plog::ColorConsoleAppender colorConsoleAppender{}; 12 | 13 | plog::init(plog::debug, &colorConsoleAppender); 14 | 15 | return Catch::Session().run(argc, argv); 16 | } 17 | -------------------------------------------------------------------------------- /tests/unit/linux/libnl-helpers/TestNetlink80211Interface.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | TEST_CASE("Nl80211Interface instance creation (nl80211)", "[linux][libnl-helpers][nl80211]") 7 | { 8 | using Microsoft::Net::Netlink::Nl80211::Nl80211Interface; 9 | 10 | SECTION("Parse doesn't cause a crash with null input") 11 | { 12 | struct nl_msg *nl80211Message{ nullptr }; 13 | REQUIRE_NOTHROW(Nl80211Interface::Parse(nl80211Message)); 14 | } 15 | 16 | SECTION("Enumerate doesn't cause a crash") 17 | { 18 | REQUIRE_NOTHROW(Nl80211Interface::Enumerate()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/unit/linux/libnl-helpers/TestNetlink80211ProtocolState.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | TEST_CASE("Netlink80211ProtocolState instance creation (nl80211)", "[linux][libnl-helpers][nl80211]") 10 | { 11 | using namespace Microsoft::Net::Netlink::Nl80211; 12 | 13 | SECTION("Create doesn't cause a crash") 14 | { 15 | REQUIRE_NOTHROW(Nl80211ProtocolState::Instance()); 16 | } 17 | 18 | SECTION("Create initializes driver id") 19 | { 20 | auto& protocolState{ Nl80211ProtocolState::Instance() }; 21 | REQUIRE(protocolState.DriverId != -1); 22 | } 23 | 24 | SECTION("Create initializes multicast group ids") 25 | { 26 | auto& protocolState{ Nl80211ProtocolState::Instance() }; 27 | REQUIRE(std::size(protocolState.MulticastGroupId) == magic_enum::enum_count()); 28 | 29 | for (const auto& [_, multicastGroupId] : protocolState.MulticastGroupId) { 30 | REQUIRE(multicastGroupId != -1); 31 | } 32 | } 33 | 34 | SECTION("Instance is a singleton") 35 | { 36 | auto& protocolState1{ Nl80211ProtocolState::Instance() }; 37 | auto& protocolState2{ Nl80211ProtocolState::Instance() }; 38 | REQUIRE(&protocolState1 == &protocolState2); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /tests/unit/linux/libnl-helpers/TestNetlinkException.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | TEST_CASE("NetlinkException", "[linux][libnl-helpers]") 7 | { 8 | using Microsoft::Net::Netlink::NetlinkException; 9 | 10 | SECTION("Does not crash") 11 | { 12 | REQUIRE_THROWS_AS(throw NetlinkException(NLE_BAD_SOCK, "test"), NetlinkException); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/unit/linux/libnl-helpers/TestNetlinkRoute.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | TEST_CASE("NetlinkEnumerateIpAddresses", "[linux][libnl-helpers]") 6 | { 7 | } 8 | 9 | TEST_CASE("NetlinkEnumerateLinks", "[linux][libnl-helpers]") 10 | { 11 | } 12 | 13 | -------------------------------------------------------------------------------- /tests/unit/linux/net/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_executable(${PROJECT_NAME}-net-linux-test-unit) 3 | 4 | target_sources(${PROJECT_NAME}-net-linux-test-unit 5 | PRIVATE 6 | Main.cxx 7 | TestNetworkOperationsLinux.cxx 8 | ) 9 | 10 | target_include_directories(${PROJECT_NAME}-net-linux-test-unit 11 | PRIVATE 12 | ${CMAKE_CURRENT_SOURCE_DIR} 13 | ) 14 | 15 | target_link_libraries(${PROJECT_NAME}-net-linux-test-unit 16 | PRIVATE 17 | Catch2::Catch2WithMain 18 | ${PROJECT_NAME}-net-linux 19 | ) 20 | 21 | catch_discover_tests(${PROJECT_NAME}-net-linux-test-unit) 22 | 23 | -------------------------------------------------------------------------------- /tests/unit/linux/net/Main.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int 9 | main(int argc, char* argv[]) 10 | { 11 | static plog::ColorConsoleAppender colorConsoleAppender{}; 12 | 13 | plog::init(plog::debug, &colorConsoleAppender); 14 | 15 | return Catch::Session().run(argc, argv); 16 | } 17 | -------------------------------------------------------------------------------- /tests/unit/linux/rfattenuator/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | find_package(Catch2 3 REQUIRED) 2 | 3 | # Allow CTest to discover Catch2 tests automatically 4 | list(APPEND CMAKE_MODULE_PATH "${catch2_SOURCE_DIR}/contrib") 5 | include(Catch) 6 | 7 | add_executable(${PROJECT_NAME}-rfattenuator-linux-test-unit) 8 | 9 | target_sources(${PROJECT_NAME}-rfattenuator-linux-test-unit 10 | PRIVATE 11 | ${CMAKE_CURRENT_LIST_DIR}/Main.cxx 12 | ${CMAKE_CURRENT_LIST_DIR}/NetRemoteRfAttenuatorServiceClient.cxx 13 | ${CMAKE_CURRENT_LIST_DIR}/../../TestNetRemoteCommon.cxx 14 | ) 15 | 16 | target_link_libraries(${PROJECT_NAME}-rfattenuator-linux-test-unit 17 | PRIVATE 18 | ${PROJECT_NAME}-net 19 | ${PROJECT_NAME}-net-test-helpers 20 | ${PROJECT_NAME}-server 21 | ${PROJECT_NAME}-rfattenuator-linux 22 | Catch2::Catch2 23 | gRPC::grpc++ 24 | magic_enum::magic_enum 25 | plog::plog 26 | wifi-test-helpers 27 | ) 28 | 29 | catch_discover_tests(${PROJECT_NAME}-rfattenuator-linux-test-unit) 30 | -------------------------------------------------------------------------------- /tests/unit/linux/rfattenuator/Main.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int 9 | main(int argc, char* argv[]) 10 | { 11 | static plog::ColorConsoleAppender colorConsoleAppender{}; 12 | 13 | plog::init(plog::debug, &colorConsoleAppender); 14 | 15 | return Catch::Session().run(argc, argv); 16 | } 17 | -------------------------------------------------------------------------------- /tests/unit/linux/wifi/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_subdirectory(apmanager) 3 | add_subdirectory(core) 4 | add_subdirectory(helpers) 5 | add_subdirectory(wpa-controller) 6 | -------------------------------------------------------------------------------- /tests/unit/linux/wifi/apmanager/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_executable(wifi-apmanager-linux-test-unit) 3 | 4 | target_sources(wifi-apmanager-linux-test-unit 5 | PRIVATE 6 | Main.cxx 7 | TestAccessPointDiscoveryAgentOperationsNetlink.cxx 8 | ) 9 | 10 | target_include_directories(wifi-apmanager-linux-test-unit 11 | PRIVATE 12 | ${CMAKE_CURRENT_SOURCE_DIR} 13 | ) 14 | 15 | target_link_libraries(wifi-apmanager-linux-test-unit 16 | PRIVATE 17 | Catch2::Catch2 18 | magic_enum::magic_enum 19 | plog::plog 20 | strings 21 | wifi-apmanager-linux 22 | wifi-test-helpers-linux 23 | ) 24 | 25 | catch_discover_tests(wifi-apmanager-linux-test-unit) 26 | -------------------------------------------------------------------------------- /tests/unit/linux/wifi/apmanager/Main.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int 9 | main(int argc, char* argv[]) 10 | { 11 | static plog::ColorConsoleAppender colorConsoleAppender{}; 12 | 13 | plog::init(plog::debug, &colorConsoleAppender); 14 | 15 | return Catch::Session().run(argc, argv); 16 | } 17 | -------------------------------------------------------------------------------- /tests/unit/linux/wifi/core/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_executable(wifi-core-linux-test-unit) 3 | 4 | target_sources(wifi-core-linux-test-unit 5 | PRIVATE 6 | TestAccessPointLinux.cxx 7 | TestAccessPointFactoryLinux.cxx 8 | ) 9 | 10 | target_include_directories(wifi-core-linux-test-unit 11 | PRIVATE 12 | ${CMAKE_CURRENT_SOURCE_DIR} 13 | ) 14 | 15 | target_link_libraries(wifi-core-linux-test-unit 16 | PRIVATE 17 | Catch2::Catch2WithMain 18 | wifi-core-linux 19 | wifi-test-helpers 20 | ) 21 | 22 | catch_discover_tests(wifi-core-linux-test-unit) 23 | -------------------------------------------------------------------------------- /tests/unit/linux/wifi/core/TestAccessPointLinux.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace Microsoft::Net::Wifi::Test 11 | { 12 | static constexpr auto InterfaceNameDefault{ "wlan0" }; 13 | } // namespace Microsoft::Net::Wifi::Test 14 | 15 | TEST_CASE("Create an AccessPointLinux instance", "[wifi][core][ap][linux]") 16 | { 17 | using namespace Microsoft::Net::Wifi; 18 | 19 | using Microsoft::Net::Netlink::Nl80211::Nl80211Interface; 20 | 21 | SECTION("Create doesn't cause a crash with null controller factory") 22 | { 23 | std::optional accessPoint; 24 | REQUIRE_NOTHROW(accessPoint.emplace(Test::InterfaceNameDefault, nullptr, Nl80211Interface{})); 25 | } 26 | 27 | SECTION("Create doesn't cause a crash") 28 | { 29 | std::optional accessPoint; 30 | REQUIRE_NOTHROW(accessPoint.emplace(Test::InterfaceNameDefault, std::make_unique(), Nl80211Interface{})); 31 | } 32 | 33 | SECTION("Create multiple for same interface doesn't cause a crash") 34 | { 35 | std::optional accessPoint1; 36 | REQUIRE_NOTHROW(accessPoint1.emplace(Test::InterfaceNameDefault, std::make_unique(), Nl80211Interface{})); 37 | 38 | std::optional accessPoint2; 39 | REQUIRE_NOTHROW(accessPoint2.emplace(Test::InterfaceNameDefault, std::make_unique(), Nl80211Interface{})); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /tests/unit/linux/wifi/helpers/AccessPointFactoryLinuxTest.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace Microsoft::Net::Wifi::Test; 9 | 10 | AccessPointFactoryLinuxTest::AccessPointFactoryLinuxTest() : 11 | AccessPointFactoryLinux{ std::make_shared() } 12 | { 13 | } 14 | -------------------------------------------------------------------------------- /tests/unit/linux/wifi/helpers/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_library(wifi-test-helpers-linux STATIC "") 3 | 4 | set(WIFI_TEST_HELPERS_LINUX_PUBLIC_INCLUDE ${CMAKE_CURRENT_LIST_DIR}/include) 5 | set(WIFI_TEST_HELPERS_LINUX_PUBLIC_INCLUDE_SUFFIX microsoft/net/wifi/test) 6 | set(WIFI_TEST_HELPERS_LINUX_PUBLIC_INCLUDE_PREFIX ${WIFI_TEST_HELPERS_LINUX_PUBLIC_INCLUDE}/${WIFI_TEST_HELPERS_LINUX_PUBLIC_INCLUDE_SUFFIX}) 7 | 8 | target_sources(wifi-test-helpers-linux 9 | PRIVATE 10 | AccessPointFactoryLinuxTest.cxx 11 | PUBLIC 12 | FILE_SET HEADERS 13 | BASE_DIRS ${WIFI_TEST_HELPERS_LINUX_PUBLIC_INCLUDE} 14 | FILES 15 | ${WIFI_TEST_HELPERS_LINUX_PUBLIC_INCLUDE_PREFIX}/AccessPointFactoryLinuxTest.hxx 16 | ) 17 | 18 | target_include_directories(wifi-test-helpers-linux 19 | PRIVATE 20 | ${CMAKE_CURRENT_SOURCE_DIR} 21 | PUBLIC 22 | ${WIFI_TEST_HELPERS_LINUX_PUBLIC_INCLUDE} 23 | ) 24 | 25 | target_link_libraries(wifi-test-helpers-linux 26 | PUBLIC 27 | wifi-core-linux 28 | wifi-test-helpers 29 | ) 30 | -------------------------------------------------------------------------------- /tests/unit/linux/wifi/helpers/include/microsoft/net/wifi/test/AccessPointFactoryLinuxTest.hxx: -------------------------------------------------------------------------------- 1 | 2 | #ifndef ACCESS_POINT_FACTORY_LINUX_TEST_HXX 3 | #define ACCESS_POINT_FACTORY_LINUX_TEST_HXX 4 | 5 | #include 6 | 7 | namespace Microsoft::Net::Wifi::Test 8 | { 9 | struct AccessPointFactoryLinuxTest : 10 | public Microsoft::Net::Wifi::AccessPointFactoryLinux 11 | { 12 | AccessPointFactoryLinuxTest(); 13 | }; 14 | } // namespace Microsoft::Net::Wifi::Test 15 | 16 | #endif // ACCESS_POINT_FACTORY_LINUX_TEST_HXX 17 | -------------------------------------------------------------------------------- /tests/unit/linux/wifi/wpa-controller/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_executable(wpa-controller-test-unit) 3 | 4 | target_sources(wpa-controller-test-unit 5 | PRIVATE 6 | detail/WifiVirtualDeviceManager.cxx 7 | detail/WpaDaemonCatch2EventListener.cxx 8 | detail/WpaDaemonManager.cxx 9 | Main.cxx 10 | TestHostapd.cxx 11 | TestWpaController.cxx 12 | TestWpaProtocolHostapd.cxx 13 | ) 14 | 15 | target_include_directories(wpa-controller-test-unit 16 | PRIVATE 17 | ${CMAKE_CURRENT_SOURCE_DIR} 18 | ${CMAKE_CURRENT_BINARY_DIR} 19 | ) 20 | 21 | target_link_libraries(wpa-controller-test-unit 22 | PRIVATE 23 | Catch2::Catch2 24 | magic_enum::magic_enum 25 | plog::plog 26 | strings 27 | wpa-controller 28 | ) 29 | 30 | configure_file( 31 | ${CMAKE_CURRENT_SOURCE_DIR}/detail/config/HostapdBinaryInfo.hxx.in 32 | ${CMAKE_CURRENT_BINARY_DIR}/HostapdBinaryInfo.hxx 33 | @ONLY 34 | ) 35 | 36 | catch_discover_tests(wpa-controller-test-unit) 37 | -------------------------------------------------------------------------------- /tests/unit/linux/wifi/wpa-controller/Main.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int main(int argc, char* argv[]) 9 | { 10 | static plog::ColorConsoleAppender colorConsoleAppender{}; 11 | 12 | plog::init(plog::debug, &colorConsoleAppender); 13 | 14 | return Catch::Session().run(argc, argv); 15 | } 16 | -------------------------------------------------------------------------------- /tests/unit/linux/wifi/wpa-controller/TestWpaProtocolHostapd.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | TEST_CASE("Test WpaKeyManagement conversions (root)", "[wpa][hostapd][client]") 6 | { 7 | using namespace Wpa; 8 | 9 | SECTION("Conversion is stable") 10 | { 11 | for (auto wpaKeyManagement : AllWpaKeyManagementsValid) { 12 | REQUIRE(WpaKeyManagementFromPropertyValue(WpaKeyManagementPropertyValue(wpaKeyManagement)) == wpaKeyManagement); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tests/unit/linux/wifi/wpa-controller/detail/WpaDaemonCatch2EventListener.hxx: -------------------------------------------------------------------------------- 1 | 2 | #ifndef WPA_DAEMON_CATCH2_EVENT_LISTENER_HXX 3 | #define WPA_DAEMON_CATCH2_EVENT_LISTENER_HXX 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include "WifiVirtualDeviceManager.hxx" 13 | #include "WpaDaemonInstance.hxx" 14 | 15 | struct WpaDaemonCatch2EventListener : 16 | public Catch::EventListenerBase 17 | { 18 | // Inherit base class constructor. 19 | using EventListenerBase::EventListenerBase; 20 | 21 | /** 22 | * @brief Runs when a test case is started. 23 | * 24 | * @param testInfo 25 | */ 26 | void 27 | testCaseStarting(Catch::TestCaseInfo const& testInfo) override; 28 | 29 | /** 30 | * @brief Runs when the last test case has ended. 31 | * 32 | * @param testCaseStats 33 | * @return * void 34 | */ 35 | void 36 | testCaseEnded(Catch::TestCaseStats const& testCaseStats) override; 37 | 38 | private: 39 | std::unordered_map> m_wpaDaemonInstances; 40 | WifiVirtualDeviceManager m_wifiVirtualDeviceManager; 41 | }; 42 | 43 | CATCH_REGISTER_LISTENER(WpaDaemonCatch2EventListener) 44 | 45 | #endif // WPA_DAEMON_CATCH2_EVENT_LISTENER_HXX 46 | -------------------------------------------------------------------------------- /tests/unit/linux/wifi/wpa-controller/detail/config/HostapdBinaryInfo.hxx.in: -------------------------------------------------------------------------------- 1 | 2 | #ifndef HOSTAPD_BINARY_INFO_HXX 3 | #define HOSTAPD_BINARY_INFO_HXX 4 | 5 | /** 6 | * Note: this is a generated file. Do not attempt to change it as any changes will be lost. 7 | */ 8 | #include 9 | 10 | namespace detail 11 | { 12 | /** 13 | * @brief The path to hostapd binaries. 14 | */ 15 | static const std::filesystem::path HostapdBinaryDirectory{ "@HOSTAP_BINARY_DIR@" }; 16 | 17 | /** 18 | * @brief The path to the hostapd daemon binary. 19 | */ 20 | static const std::filesystem::path HostapdBinaryPath{ HostapdBinaryDirectory / "hostapd" }; 21 | } // namespace detail 22 | 23 | #endif // HOSTAPD_BINARY_INFO_HXX 24 | -------------------------------------------------------------------------------- /tests/unit/net/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_subdirectory(helpers) 3 | add_subdirectory(wifi) 4 | -------------------------------------------------------------------------------- /tests/unit/net/helpers/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_library(${PROJECT_NAME}-net-test-helpers STATIC "") 3 | 4 | set(NET_TEST_HELPERS_PUBLIC_INCLUDE ${CMAKE_CURRENT_LIST_DIR}/include) 5 | set(NET_TEST_HELPERS_PUBLIC_INCLUDE_SUFFIX microsoft/net/test) 6 | set(NET_TEST_HELPERS_PUBLIC_INCLUDE_PREFIX ${NET_TEST_HELPERS_PUBLIC_INCLUDE}/${NET_TEST_HELPERS_PUBLIC_INCLUDE_SUFFIX}) 7 | 8 | target_sources(${PROJECT_NAME}-net-test-helpers 9 | PRIVATE 10 | NetworkOperationsTest.cxx 11 | PUBLIC 12 | FILE_SET HEADERS 13 | BASE_DIRS ${NET_TEST_HELPERS_PUBLIC_INCLUDE} 14 | FILES 15 | ${NET_TEST_HELPERS_PUBLIC_INCLUDE_PREFIX}/NetworkOperationsTest.hxx 16 | ) 17 | 18 | target_include_directories(${PROJECT_NAME}-net-test-helpers 19 | PRIVATE 20 | ${CMAKE_CURRENT_SOURCE_DIR} 21 | PUBLIC 22 | ${NET_TEST_HELPERS_PUBLIC_INCLUDE} 23 | ) 24 | 25 | target_link_libraries(netremote-net-test-helpers 26 | PUBLIC 27 | ${PROJECT_NAME}-net 28 | ) 29 | -------------------------------------------------------------------------------- /tests/unit/net/wifi/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_subdirectory(apmanager) 3 | add_subdirectory(core) 4 | add_subdirectory(helpers) 5 | -------------------------------------------------------------------------------- /tests/unit/net/wifi/apmanager/AccessPointDiscoveryAgentOperationsTest.hxx: -------------------------------------------------------------------------------- 1 | 2 | #ifndef ACCESS_POINT_DISCOVERY_AGENT_TEST_HXX 3 | #define ACCESS_POINT_DISCOVERY_AGENT_TEST_HXX 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | namespace Microsoft::Net::Wifi::Test 16 | { 17 | /** 18 | * @brief Access point discovery operations for use in unit tests. 19 | */ 20 | struct AccessPointDiscoveryAgentOperationsTest : 21 | public Microsoft::Net::Wifi::IAccessPointDiscoveryAgentOperations 22 | { 23 | AccessPointDiscoveryAgentOperationsTest(); 24 | 25 | void 26 | Start(AccessPointPresenceEventCallback callback) override; 27 | 28 | void 29 | Stop() override; 30 | 31 | std::future>> 32 | ProbeAsync() override; 33 | 34 | void 35 | AddAccessPoint(std::string_view accessPointInterfaceNameToAdd); 36 | 37 | void 38 | RemoveAccessPoint(std::string_view accessPointInterfaceNameToRemove); 39 | 40 | private: 41 | AccessPointPresenceEventCallback m_callback; 42 | std::vector> m_accessPoints; 43 | std::unique_ptr m_accessPointFactory; 44 | }; 45 | 46 | } // namespace Microsoft::Net::Wifi::Test 47 | 48 | #endif // ACCESS_POINT_DISCOVERY_AGENT_TEST_HXX 49 | -------------------------------------------------------------------------------- /tests/unit/net/wifi/apmanager/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_executable(wifi-apmanager-test-unit) 3 | 4 | target_sources(wifi-apmanager-test-unit 5 | PRIVATE 6 | AccessPointDiscoveryAgentOperationsTest.cxx 7 | AccessPointDiscoveryAgentOperationsTest.hxx 8 | TestAccessPointDiscoveryAgent.cxx 9 | TestAccessPointManager.cxx 10 | ) 11 | 12 | target_include_directories(wifi-apmanager-test-unit 13 | PRIVATE 14 | ${CMAKE_CURRENT_SOURCE_DIR} 15 | ) 16 | 17 | target_link_libraries(wifi-apmanager-test-unit 18 | PRIVATE 19 | Catch2::Catch2WithMain 20 | magic_enum::magic_enum 21 | strings 22 | wifi-apmanager 23 | wifi-test-helpers 24 | ) 25 | 26 | catch_discover_tests(wifi-apmanager-test-unit) 27 | -------------------------------------------------------------------------------- /tests/unit/net/wifi/core/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_executable(wifi-core-test-unit) 3 | 4 | target_sources(wifi-core-test-unit 5 | PRIVATE 6 | Main.cxx 7 | TestAccessPoint.cxx 8 | TestAccessPointAttributes.cxx 9 | TestAccessPointOperationStatus.cxx 10 | TestIeee80211.cxx 11 | ) 12 | 13 | target_include_directories(wifi-core-test-unit 14 | PRIVATE 15 | ${CMAKE_CURRENT_SOURCE_DIR} 16 | ) 17 | 18 | target_link_libraries(wifi-core-test-unit 19 | PRIVATE 20 | Catch2::Catch2 21 | magic_enum::magic_enum 22 | nlohmann_json::nlohmann_json 23 | plog::plog 24 | strings 25 | wifi-core 26 | wifi-test-helpers 27 | ) 28 | 29 | catch_discover_tests(wifi-core-test-unit) 30 | -------------------------------------------------------------------------------- /tests/unit/net/wifi/core/Main.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int 9 | main(int argc, char* argv[]) 10 | { 11 | static plog::ColorConsoleAppender colorConsoleAppender{}; 12 | 13 | plog::init(plog::debug, &colorConsoleAppender); 14 | 15 | return Catch::Session().run(argc, argv); 16 | } 17 | -------------------------------------------------------------------------------- /tests/unit/net/wifi/helpers/AccessPointManagerTest.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace Microsoft::Net::Wifi::Test; 10 | 11 | void 12 | AccessPointManagerTest::AddAccessPoint(std::shared_ptr accessPoint) 13 | { 14 | return AccessPointManager::AddAccessPoint(std::move(accessPoint)); 15 | } 16 | 17 | void 18 | AccessPointManagerTest::RemoveAccessPoint(std::shared_ptr accessPoint) 19 | { 20 | return AccessPointManager::RemoveAccessPoint(std::move(accessPoint)); 21 | } 22 | -------------------------------------------------------------------------------- /tests/unit/net/wifi/helpers/AccessPointTest.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | using namespace Microsoft::Net::Wifi; 13 | using namespace Microsoft::Net::Wifi::Test; 14 | 15 | AccessPointTest::AccessPointTest(std::string_view interfaceName, Ieee80211AccessPointCapabilities capabilities, AccessPointAttributes attributes) : 16 | InterfaceName(interfaceName), 17 | Capabilities(std::move(capabilities)), 18 | Attributes(std::move(attributes)) 19 | {} 20 | 21 | std::string_view 22 | AccessPointTest::GetInterfaceName() const noexcept 23 | { 24 | return InterfaceName; 25 | } 26 | 27 | Ieee80211MacAddress 28 | AccessPointTest::GetMacAddress() const noexcept 29 | { 30 | return MacAddress; 31 | } 32 | 33 | const AccessPointAttributes& 34 | AccessPointTest::GetAttributes() const noexcept 35 | { 36 | return Attributes; 37 | } 38 | 39 | std::unique_ptr 40 | AccessPointTest::CreateController() 41 | { 42 | return std::make_unique(this); 43 | } 44 | 45 | std::shared_ptr 46 | AccessPointFactoryTest::Create(std::string_view interfaceName, [[maybe_unused]] std::unique_ptr createArgs) 47 | { 48 | return std::make_shared(interfaceName); 49 | } 50 | -------------------------------------------------------------------------------- /tests/unit/net/wifi/helpers/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_library(wifi-test-helpers STATIC "") 3 | 4 | set(WIFI_TEST_HELPERS_PUBLIC_INCLUDE ${CMAKE_CURRENT_LIST_DIR}/include) 5 | set(WIFI_TEST_HELPERS_PUBLIC_INCLUDE_SUFFIX microsoft/net/wifi/test) 6 | set(WIFI_TEST_HELPERS_PUBLIC_INCLUDE_PREFIX ${WIFI_TEST_HELPERS_PUBLIC_INCLUDE}/${WIFI_TEST_HELPERS_PUBLIC_INCLUDE_SUFFIX}) 7 | 8 | target_sources(wifi-test-helpers 9 | PRIVATE 10 | AccessPointControllerTest.cxx 11 | AccessPointManagerTest.cxx 12 | AccessPointTest.cxx 13 | PUBLIC 14 | FILE_SET HEADERS 15 | BASE_DIRS ${WIFI_TEST_HELPERS_PUBLIC_INCLUDE} 16 | FILES 17 | ${WIFI_TEST_HELPERS_PUBLIC_INCLUDE_PREFIX}/AccessPointControllerTest.hxx 18 | ${WIFI_TEST_HELPERS_PUBLIC_INCLUDE_PREFIX}/AccessPointManagerTest.hxx 19 | ${WIFI_TEST_HELPERS_PUBLIC_INCLUDE_PREFIX}/AccessPointTest.hxx 20 | ) 21 | 22 | target_include_directories(wifi-test-helpers 23 | PRIVATE 24 | ${CMAKE_CURRENT_SOURCE_DIR} 25 | PUBLIC 26 | ${WIFI_TEST_HELPERS_PUBLIC_INCLUDE} 27 | ) 28 | 29 | target_link_libraries(wifi-test-helpers 30 | PUBLIC 31 | wifi-apmanager 32 | wifi-core 33 | ) 34 | -------------------------------------------------------------------------------- /tests/unit/net/wifi/helpers/include/microsoft/net/wifi/test/AccessPointManagerTest.hxx: -------------------------------------------------------------------------------- 1 | 2 | #ifndef ACCESS_POINT_MANAGER_TEST 3 | #define ACCESS_POINT_MANAGER_TEST 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | namespace Microsoft::Net::Wifi::Test 11 | { 12 | /** 13 | * @brief AccessPointManager to be used in tests, allowing access to protected methods to add/remove known access 14 | * points. 15 | */ 16 | struct AccessPointManagerTest : 17 | public Microsoft::Net::Wifi::AccessPointManager 18 | { 19 | /** 20 | * @brief Construct a new AccessPointManagerTest object. 21 | */ 22 | AccessPointManagerTest() = default; 23 | 24 | /** 25 | * @brief Adds a new access point. 26 | * 27 | * @param accessPoint The access point to add. 28 | */ 29 | void 30 | AddAccessPoint(std::shared_ptr accessPoint) override; 31 | 32 | /** 33 | * @brief Removes an existing access point from use. 34 | * 35 | * @param accessPoint The access point to remove. 36 | */ 37 | void 38 | RemoveAccessPoint(std::shared_ptr accessPoint) override; 39 | }; 40 | } // namespace Microsoft::Net::Wifi::Test 41 | 42 | #endif // ACCESS_POINT_MANAGER_TEST 43 | --------------------------------------------------------------------------------