From d445e3d7d802e5c1ea918df5a07cfaa9f01aef94 Mon Sep 17 00:00:00 2001 From: Jussi Kuokkanen Date: Wed, 6 May 2020 20:40:48 +0300 Subject: [PATCH] add hashes for nodes for persistent identification --- src/include/Crypto.hpp | 10 ++++++++ src/include/Device.hpp | 2 +- src/lib/Crypto.cpp | 32 +++++++++++++++++++++++ src/plugins/Nvidia.cpp | 41 ++++++++++++++++++++++++------ src/plugins/meson.build | 3 ++- src/tuxclockerd/AdaptorFactory.hpp | 4 +-- src/tuxclockerd/Adaptors.hpp | 8 +++--- src/tuxclockerd/main.cpp | 25 ++++++++++++++---- 8 files changed, 105 insertions(+), 20 deletions(-) create mode 100644 src/include/Crypto.hpp create mode 100644 src/lib/Crypto.cpp diff --git a/src/include/Crypto.hpp b/src/include/Crypto.hpp new file mode 100644 index 0000000..a13b886 --- /dev/null +++ b/src/include/Crypto.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include + +namespace TuxClocker::Crypto { + +std::string sha256(std::string s); +std::string md5(std::string s); + +}; diff --git a/src/include/Device.hpp b/src/include/Device.hpp index e37f332..d285b93 100644 --- a/src/include/Device.hpp +++ b/src/include/Device.hpp @@ -77,8 +77,8 @@ using DeviceInterface = std::variant; struct DeviceNode { std::string name; std::optional interface; + std::string hash; }; - }; }; diff --git a/src/lib/Crypto.cpp b/src/lib/Crypto.cpp new file mode 100644 index 0000000..e712441 --- /dev/null +++ b/src/lib/Crypto.cpp @@ -0,0 +1,32 @@ +#include +#include +#include + +namespace TuxClocker::Crypto { + +std::string sha256(std::string s) { + auto d = SHA256(reinterpret_cast(s.c_str()), s.size(), 0); + + char out[(SHA256_DIGEST_LENGTH * 2) + 1]; + + for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) + sprintf(out + (i * 2), "%02x", d[i]); + + out[SHA256_DIGEST_LENGTH * 2] = '\0'; + return std::string(out); +} + +std::string md5(std::string s) { + unsigned char data[MD5_DIGEST_LENGTH]; + MD5(reinterpret_cast(s.c_str()), s.size(), data); + + char out[(MD5_DIGEST_LENGTH * 2) + 1]; + + for (int i = 0; i < MD5_DIGEST_LENGTH; i++) + sprintf(out + (i * 2), "%02x", data[i]); + + out[MD5_DIGEST_LENGTH * 2] = '\0'; + return std::string(out); +} + +}; diff --git a/src/plugins/Nvidia.cpp b/src/plugins/Nvidia.cpp index 548e3d3..c04db5a 100644 --- a/src/plugins/Nvidia.cpp +++ b/src/plugins/Nvidia.cpp @@ -1,3 +1,4 @@ +#include #include #include @@ -10,6 +11,7 @@ #include using namespace TuxClocker; +using namespace TuxClocker::Crypto; using namespace TuxClocker::Device; using namespace TuxClocker::Plugin; using namespace mpark::patterns; @@ -34,6 +36,18 @@ struct UnspecializedReadable { std::function(T)> func; std::optional unit; std::string nodeName; + // One time function for getting a hash + std::function hash; + + static std::vector toDeviceNodes( + std::vector> rawNodes, T data, std::string uuid) { + std::vector retval; + + for (const auto &rawNode : rawNodes) { + + } + return retval; + } }; template @@ -43,10 +57,11 @@ struct UnspecializedAssignable { std::function(T, AssignableInfo, AssignmentArgument)> func; std::optional unit; std::string nodeName; + std::function hash; static std::vector toDeviceNodes( std::vector> rawNodes, - T devData) { + T devData, std::string uuid) { std::vector retval; for (auto &rawNode : rawNodes) { if_let(pattern(some(arg)) = rawNode.assignableInfo(devData)) = [&](auto info) { @@ -55,7 +70,8 @@ struct UnspecializedAssignable { }, info); auto node = DeviceNode { .name = rawNode.nodeName, - .interface = assignable + .interface = assignable, + .hash = rawNode.hash(uuid, devData) }; retval.push_back(node); }; @@ -259,7 +275,10 @@ NvidiaPlugin::NvidiaPlugin() : m_dpy() { return retval; }, "W", - "Power Limit" + "Power Limit", + [](std::string uuid, nvmlDevice_t) { + return md5(uuid + "Power Limit"); + } } }; @@ -297,7 +316,10 @@ NvidiaPlugin::NvidiaPlugin() : m_dpy() { return retval; }, "MHz", - "Memory Clock Offset" + "Memory Clock Offset", + [](std::string uuid, NVClockInfo) { + return md5(uuid + "Memory Clock Offset"); + } } }; @@ -335,7 +357,10 @@ NvidiaPlugin::NvidiaPlugin() : m_dpy() { return ret; }, std::nullopt, - "Fan Mode" + "Fan Mode", + [](std::string uuid, uint) { + return md5(uuid + "Fan Mode"); + } } }; @@ -448,7 +473,7 @@ NvidiaPlugin::NvidiaPlugin() : m_dpy() { gpuRoot.appendChild(specNode); for (auto &node : UnspecializedAssignable::toDeviceNodes( - rawNVMLAssignables, dev)) + rawNVMLAssignables, dev, nvOpt.uuid)) gpuRoot.appendChild(node); }; @@ -472,11 +497,11 @@ NvidiaPlugin::NvidiaPlugin() : m_dpy() { auto clockInfo = NVClockInfo{nvctrlPerfModes(index), index}; for (auto &node : UnspecializedAssignable::toDeviceNodes( - rawNVCTRLClockAssignables, clockInfo)) + rawNVCTRLClockAssignables, clockInfo, nvOpt.uuid)) gpuRoot.appendChild(node); for (auto &node : UnspecializedAssignable::toDeviceNodes( - rawNVCTRLAssignables, index)) + rawNVCTRLAssignables, index, nvOpt.uuid)) gpuRoot.appendChild(node); }; diff --git a/src/plugins/meson.build b/src/plugins/meson.build index ec13abf..44e1d1c 100644 --- a/src/plugins/meson.build +++ b/src/plugins/meson.build @@ -34,5 +34,6 @@ if all_nvidia_linux_libs include_directories : [incdir, patterns_inc, fplus_inc], dependencies : [nvidia_linux_libs, boost_dep], install_dir : get_option('libdir') / 'tuxclocker' / 'plugins', - install : true) + install : true, + link_with : libtuxclocker) endif diff --git a/src/tuxclockerd/AdaptorFactory.hpp b/src/tuxclockerd/AdaptorFactory.hpp index 3d971ba..111fa20 100644 --- a/src/tuxclockerd/AdaptorFactory.hpp +++ b/src/tuxclockerd/AdaptorFactory.hpp @@ -16,14 +16,14 @@ public: /* Returns a raw pointer since smart pointers caused some scope issues. * TODO: try to use smart pointers instead? */ static std::optional adaptor(QObject *obj, - DeviceInterface iface) { + DeviceInterface iface, DeviceNode devNode) { std::optional retval = std::nullopt; match(iface) (pattern(as(arg)) = [&](auto dr) { retval = new DynamicReadableAdaptor(obj, dr); }, pattern(as(arg)) = [&](auto a) { - retval = new AssignableAdaptor(obj, a); + retval = new AssignableAdaptor(obj, a, devNode); }, pattern(_) = []{}); return retval; diff --git a/src/tuxclockerd/Adaptors.hpp b/src/tuxclockerd/Adaptors.hpp index b3f8087..565f9db 100644 --- a/src/tuxclockerd/Adaptors.hpp +++ b/src/tuxclockerd/Adaptors.hpp @@ -63,8 +63,8 @@ Q_DECLARE_METATYPE(TCDBus::Result) class AssignableAdaptor : public QDBusAbstractAdaptor { public: - explicit AssignableAdaptor(QObject *obj, Assignable a) : QDBusAbstractAdaptor(obj), - m_assignable(a) { + explicit AssignableAdaptor(QObject *obj, Assignable a, DeviceNode devNode) : + QDBusAbstractAdaptor(obj), m_assignable(a), m_devNode(devNode) { qDBusRegisterMetaType(); qDBusRegisterMetaType(); qDBusRegisterMetaType>(); @@ -99,6 +99,7 @@ public: m_dbusAssignableInfo = QDBusVariant(a_info); } QDBusVariant assignableInfo_() {return m_dbusAssignableInfo;} + QString hash_() {return QString::fromStdString(m_devNode.hash);} public Q_SLOTS: TCDBus::Result assign(QDBusVariant arg_) { auto v = arg_.variant(); @@ -132,8 +133,10 @@ private: Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.tuxclocker.Assignable") Q_PROPERTY(QDBusVariant assignableInfo READ assignableInfo_) + Q_PROPERTY(QString hash READ hash_) Assignable m_assignable; + DeviceNode m_devNode; QDBusVariant m_dbusAssignableInfo; }; @@ -155,7 +158,6 @@ public: childIndices.append(i); TCDBus::FlatTreeNode fn{f_node.value, childIndices}; - qDebug("Hello"); m_flatTree.append(fn); } } diff --git a/src/tuxclockerd/main.cpp b/src/tuxclockerd/main.cpp index 7e4dad3..2ac9a90 100644 --- a/src/tuxclockerd/main.cpp +++ b/src/tuxclockerd/main.cpp @@ -28,21 +28,36 @@ int main(int argc, char **argv) { TreeNode dbusRootNode; std::function, QString, TreeNode*)> traverse; - traverse = [&traverse, &connection, &adaptors, &root, &dbusRootNode]( + traverse = [&traverse, &connection, &adaptors, &root]( TreeNode node, QString parentPath, TreeNode *dbusNode) { auto obj = new QObject(&root); // Is destroyed when root goes out of scope // Remove whitespaces to make valid object paths auto objName = QString::fromStdString(node.value().name).replace(" ", ""); auto thisPath = parentPath + objName; + QString ifaceName; if_let(pattern(some(arg)) = node.value().interface) = [&](auto iface) { - if_let(pattern(some(arg)) = AdaptorFactory::adaptor(obj, iface)) = [&](auto adaptor) { + if_let(pattern(some(arg)) = + AdaptorFactory::adaptor(obj, iface, node.value())) = [&](auto adaptor) { adaptors.append(adaptor); - connection.registerObject(thisPath, obj); + connection.registerObject(thisPath, obj); + + // TODO: don't hardcode interface name + // Maybe create an intermediate class that contains the interface name to avoid this + // For some reason this throws a bad_cast when using 'as' with pointer type + match(*adaptor) + (pattern(as(_)) = [&] { + ifaceName = "org.tuxclocker.Assignable"; + }, + pattern(as(_)) = [&] { + ifaceName = "org.tuxclocker.DynamicReadable"; + }, + pattern(_) = [] {}); }; }; - auto thisDBusNode = new TreeNode{{thisPath, "org.tuxclocker"}}; - dbusNode->appendChild(*thisDBusNode); + + auto thisDBusNode = TreeNode{{thisPath, ifaceName}}; + dbusNode->appendChild(thisDBusNode); qDebug() << thisPath; for (const auto &child : node.children()) traverse(child, thisPath + "/", &dbusNode->childrenPtr()->back());