Skip to content

Commit

Permalink
Add cli foundation.
Browse files Browse the repository at this point in the history
  • Loading branch information
abeltrano committed Jan 18, 2024
1 parent c5ef19f commit 2c7a301
Show file tree
Hide file tree
Showing 11 changed files with 285 additions and 97 deletions.
19 changes: 19 additions & 0 deletions src/common/client/include/microsoft/net/remote/NetRemoteClient.hxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@

#ifndef NET_REMOTE_CLIENT
#define NET_REMOTE_CLIENT

#include <string_view>

namespace Microsoft::Net::Remote
{
/**
* @brief Identifiers for commands supported by the server.
*/
enum class NetRemoteCommandId
{
None,
WifiEnumerateAcessPoints,
};
} // namespace Microsoft::Net::Remote

#endif // NET_REMOTE_CLIENT
2 changes: 2 additions & 0 deletions src/common/tools/cli/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ target_sources(${PROJECT_NAME}-cli
PRIVATE
NetRemoteCli.cxx
NetRemoteCliHandler.cxx
NetRemoteCliHandlerOperations.cxx
PUBLIC
FILE_SET HEADERS
BASE_DIRS ${NETREMOTE_CLI_PUBLIC_INCLUDE}
Expand All @@ -17,6 +18,7 @@ target_sources(${PROJECT_NAME}-cli
${NETREMOTE_CLI_PUBLIC_INCLUDE_PREFIX}/NetRemoteCli.hxx
${NETREMOTE_CLI_PUBLIC_INCLUDE_PREFIX}/NetRemoteCliData.hxx
${NETREMOTE_CLI_PUBLIC_INCLUDE_PREFIX}/NetRemoteCliHandler.hxx
${NETREMOTE_CLI_PUBLIC_INCLUDE_PREFIX}/NetRemoteCliHandlerOperations.hxx
)

target_link_libraries(${PROJECT_NAME}-cli
Expand Down
65 changes: 61 additions & 4 deletions src/common/tools/cli/NetRemoteCli.cxx
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@

#include <string>

#include <microsoft/net/remote/NetRemoteCli.hxx>
#include <notstd/Memory.hxx>
#include <plog/Log.h>

using namespace Microsoft::Net::Remote;

Expand All @@ -15,7 +18,7 @@ NetRemoteCli::NetRemoteCli(std::shared_ptr<NetRemoteCliData> cliData, std::share
std::shared_ptr<NetRemoteCli>
NetRemoteCli::Create(std::shared_ptr<NetRemoteCliData> cliData, std::shared_ptr<NetRemoteCliHandler> cliHandler)
{
auto instance = std::make_shared<notstd::enable_make_protected<NetRemoteCli>>(std::move(cliData), std::move(cliHandler));
auto instance = std::make_shared<notstd::enable_make_protected<NetRemoteCli>>(std::move(cliData), cliHandler);
cliHandler->SetParent(instance->weak_from_this());

return std::move(instance);
Expand All @@ -40,6 +43,8 @@ NetRemoteCli::Parse(int argc, char* argv[]) noexcept
m_cliApp->parse(argc, argv);
} catch (const CLI::ParseError& e) {
return m_cliApp->exit(e);
} catch (...) {
LOGF << "Unhandled exception";
}

return 0;
Expand All @@ -48,10 +53,62 @@ NetRemoteCli::Parse(int argc, char* argv[]) noexcept
std::unique_ptr<CLI::App>
NetRemoteCli::CreateParser() noexcept
{
auto app = std::make_unique<CLI::App>("A command line tool to intercat with netremote servers", "netremote-cli");
auto app = std::make_unique<CLI::App>("A command line tool to interact with netremote servers", "netremote-cli");

app->require_subcommand();

auto optionServer = app->add_option_function<std::string>("-s,--server", [this](const std::string& serverAddress) {
OnServerAddressChanged(serverAddress);
});
optionServer->description("The address of the netremote server to connect to");

app->add_option("-s,--server", m_cliData->ServerAddress, "Server address")->default_str(m_cliData->ServerAddress);
app->add_option("-c,--command", m_cliData->Command, "Command");
m_cliAppServerAddress = optionServer;
m_cliAppWifi = AddSubcommandWifi(app.get());

return app;
}

CLI::App*
NetRemoteCli::AddSubcommandWifi(CLI::App* parent)
{
// Top-level command.
auto* wifiApp = parent->add_subcommand("wifi", "Wi-Fi operations");
wifiApp->needs(m_cliAppServerAddress);

// Sub-commands.
m_cliAppWifiEnumerateAccessPoints = AddSubcommandWifiEnumerateAccessPoints(wifiApp);

return wifiApp;
}

CLI::App*
NetRemoteCli::AddSubcommandWifiEnumerateAccessPoints(CLI::App* parent)
{
auto cliAppWifiEnumerateAccessPoints = parent->add_subcommand("enumerate-access-points", "Enumerate available Wi-Fi access points");
cliAppWifiEnumerateAccessPoints->alias("enumaps");
cliAppWifiEnumerateAccessPoints->callback([this] {
OnWifiEnumerateAccessPoints();
});

return cliAppWifiEnumerateAccessPoints;
}

void
NetRemoteCli::OnServerAddressChanged(const std::string& serverAddress)
{
m_cliData->ServerAddress = serverAddress;

auto connection = NetRemoteServerConnection::TryEstablishConnection(serverAddress);
if (connection == nullptr) {
LOGE << "Failed to create server connection";
return;
}

m_cliHandler->SetConnection(std::move(connection));
}

void
NetRemoteCli::OnWifiEnumerateAccessPoints()
{
m_cliHandler->HandleCommandWifiEnumerateAccessPoints();
}
11 changes: 9 additions & 2 deletions src/common/tools/cli/NetRemoteCliHandler.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@

using namespace Microsoft::Net::Remote;

NetRemoteCliHandler::NetRemoteCliHandler(std::shared_ptr<INetRemoteCliHandlerOperations> operations) :
m_operations(std::move(operations))
NetRemoteCliHandler::NetRemoteCliHandler(std::unique_ptr<INetRemoteCliHandlerOperationsFactory> operationsFactory) :
m_operationsFactory(std::move(operationsFactory))
{
}

Expand All @@ -17,6 +17,13 @@ NetRemoteCliHandler::SetParent(std::weak_ptr<NetRemoteCli> parent)
m_parent = parent;
}

void
NetRemoteCliHandler::SetConnection(std::shared_ptr<NetRemoteServerConnection> connection)
{
m_connection = connection;
m_operations = m_operationsFactory->Create(m_connection);
}

std::shared_ptr<NetRemoteCli>
NetRemoteCliHandler::GetParentStrongRef() const
{
Expand Down
38 changes: 38 additions & 0 deletions src/common/tools/cli/NetRemoteCliHandlerOperations.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#include <format>

#include <grpcpp/client_context.h>
#include <magic_enum.hpp>
#include <microsoft/net/remote/NetRemoteCliHandlerOperations.hxx>
#include <microsoft/net/remote/protocol/NetRemoteService.grpc.pb.h>
#include <plog/Log.h>

using namespace Microsoft::Net::Remote;

using namespace Microsoft::Net::Remote;
using namespace Microsoft::Net::Remote::Service;
using namespace Microsoft::Net::Remote::Wifi;

NetRemoteCliHandlerOperations::NetRemoteCliHandlerOperations(std::shared_ptr<NetRemoteServerConnection> connection) :
m_connection(std::move(connection))
{
}

void
NetRemoteCliHandlerOperations::WifiEnumerateAccessPoints()
{
WifiEnumerateAccessPointsRequest request{};
WifiEnumerateAccessPointsResult result{};
grpc::ClientContext clientContext{};

auto status = m_connection->Client->WifiEnumerateAccessPoints(&clientContext, request, &result);
if (!status.ok()) {
LOGE << std::format("Failed to enumerate WiFi access points, error={} details={} message={}", magic_enum::enum_name(status.error_code()), status.error_details(), status.error_message());
return;
}
}

std::unique_ptr<INetRemoteCliHandlerOperations>
NetRemoteCliHandlerOperationsFactory::Create(std::shared_ptr<NetRemoteServerConnection> connection)
{
return std::make_unique<NetRemoteCliHandlerOperations>(std::move(connection));
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@
#ifndef I_NET_REMOTE_CLI_HANDLER_OPERATIONS_HXX
#define I_NET_REMOTE_CLI_HANDLER_OPERATIONS_HXX

#include <memory>

#include <microsoft/net/remote/NetRemoteServerConnection.hxx>

namespace Microsoft::Net::Remote
{
/**
* @brief Operations that can be carried out by a NetRemote CLI handler.
*
*/
struct INetRemoteCliHandlerOperations
{
Expand All @@ -18,6 +21,23 @@ struct INetRemoteCliHandlerOperations
virtual void
WifiEnumerateAccessPoints() = 0;
};

/**
* @brief Factory to create instances of INetRemoteCliHandlerOperations.
*/
struct INetRemoteCliHandlerOperationsFactory
{
virtual ~INetRemoteCliHandlerOperationsFactory() = default;

/**
* @brief Create a new INetRemoteCliHandlerOperationsFactory instance with the specified server connection.
*
* @param connection The server connection the handler will use to carry out operations.
* @return std::unique_ptr<INetRemoteCliHandlerOperations>
*/
virtual std::unique_ptr<INetRemoteCliHandlerOperations>
Create(std::shared_ptr<NetRemoteServerConnection> connection) = 0;
};
} // namespace Microsoft::Net::Remote

#endif // I_NET_REMOTE_CLI_HANDLER_OPERATIONS_HXX
39 changes: 39 additions & 0 deletions src/common/tools/cli/include/microsoft/net/remote/NetRemoteCli.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <CLI/CLI.hpp>
#include <microsoft/net/remote/NetRemoteCliData.hxx>
#include <microsoft/net/remote/NetRemoteCliHandler.hxx>
#include <microsoft/net/remote/NetRemoteServerConnection.hxx>

namespace Microsoft::Net::Remote
{
Expand Down Expand Up @@ -75,10 +76,48 @@ private:
std::unique_ptr<CLI::App>
CreateParser() noexcept;

/**
* @brief Add the 'wifi' sub-command.
*
* @param parent The parent app to add the sub-command to.
* @return CLI::App*
*/
CLI::App*
AddSubcommandWifi(CLI::App* parent);

/**
* @brief Add the 'wifi enumerate-access-points' sub-command.
*
* @param parent The parent app to add the sub-command to.
* @return CLI::App*
*/
CLI::App*
AddSubcommandWifiEnumerateAccessPoints(CLI::App* parent);

/**
* @brief Handle the 'server' option.
*
* @param serverAddress The server address to connect to.
*/
void
OnServerAddressChanged(const std::string& serverAddress);

/**
* @brief Handle the 'wifi enumerate-access-points' command.
*/
void
OnWifiEnumerateAccessPoints();

private:
std::shared_ptr<NetRemoteCliData> m_cliData;
std::shared_ptr<NetRemoteCliHandler> m_cliHandler;
std::unique_ptr<CLI::App> m_cliApp;
std::shared_ptr<NetRemoteServerConnection> m_connection;

// The following are helper references to the subcommands of m_cliApp; the memory is managed by CLI11.
CLI::Option* m_cliAppServerAddress{ nullptr };
CLI::App* m_cliAppWifi{ nullptr };
CLI::App* m_cliAppWifiEnumerateAccessPoints{ nullptr };
};
} // namespace Microsoft::Net::Remote

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@

#include <memory>

#include <microsoft/net/remote/NetRemoteServerConnection.hxx>

namespace Microsoft::Net::Remote
{
struct INetRemoteCliHandlerOperations;
struct INetRemoteCliHandlerOperationsFactory;
struct NetRemoteCli;

/**
Expand All @@ -19,9 +22,9 @@ struct NetRemoteCliHandler
/**
* @brief Construct a new NetRemoteCliHandler object.
*
* @param operations The operations instance to use for handling commands.
* @param operationsFactory The factory to use to create the operations instance to use for handling commands.
*/
NetRemoteCliHandler(std::shared_ptr<INetRemoteCliHandlerOperations> operations);
NetRemoteCliHandler(std::unique_ptr<INetRemoteCliHandlerOperationsFactory> operationsFactory);

/**
* @brief Assign the parent NetRemoteCli object.
Expand All @@ -31,6 +34,14 @@ struct NetRemoteCliHandler
void
SetParent(std::weak_ptr<NetRemoteCli> parent);

/**
* @brief Set the connection object to use.
*
* @param connection
*/
void
SetConnection(std::shared_ptr<NetRemoteServerConnection> connection);

/**
* @brief Handle a command request to enumerate available Wi-Fi access points.
*/
Expand All @@ -49,7 +60,9 @@ private:

private:
std::weak_ptr<NetRemoteCli> m_parent;
std::unique_ptr<INetRemoteCliHandlerOperationsFactory> m_operationsFactory;
std::shared_ptr<INetRemoteCliHandlerOperations> m_operations;
std::shared_ptr<NetRemoteServerConnection> m_connection;
};
} // namespace Microsoft::Net::Remote

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@

#ifndef NET_REMOTE_CLI_HANDLER_OPERATIONS_HXX
#define NET_REMOTE_CLI_HANDLER_OPERATIONS_HXX

#include <memory>

#include <microsoft/net/remote/INetRemoteCliHandlerOperations.hxx>
#include <microsoft/net/remote/NetRemoteServerConnection.hxx>

namespace Microsoft::Net::Remote
{
/**
* @brief Base implementation for handling CLI operations. This uses a remote server connection to carry out the
* operations.
*/
struct NetRemoteCliHandlerOperations :
public INetRemoteCliHandlerOperations
{
virtual ~NetRemoteCliHandlerOperations() = default;

/**
* @brief Construct a new NetRemoteCliHandlerOperations object with the specified server connection.
*
* @param connection The server connection to use to carry out operations.
*/
NetRemoteCliHandlerOperations(std::shared_ptr<NetRemoteServerConnection> connection);

/**
* @brief Enumerate available WiFi access points.
*/
virtual void
WifiEnumerateAccessPoints() override;

private:
std::shared_ptr<NetRemoteServerConnection> m_connection;
};

struct NetRemoteCliHandlerOperationsFactory :
public INetRemoteCliHandlerOperationsFactory
{
virtual ~NetRemoteCliHandlerOperationsFactory() = default;

/**
* @brief Create a new INetRemoteCliHandlerOperationsFactory instance with the specified server connection.
*
* @param connection The server connection the handler will use to carry out operations.
* @return std::unique_ptr<INetRemoteCliHandlerOperations>
*/
virtual std::unique_ptr<INetRemoteCliHandlerOperations>
Create(std::shared_ptr<NetRemoteServerConnection> connection) override;
};
} // namespace Microsoft::Net::Remote

#endif // NET_REMOTE_CLI_HANDLER_OPERATIONS_HXX
Loading

0 comments on commit 2c7a301

Please sign in to comment.