1// Copyright (C) 2017 Ford Motor Company
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#include "qremoteobjectregistry.h"
6#include "qremoteobjectreplica_p.h"
7
8#include <private/qobject_p.h>
9#include <QtCore/qset.h>
10#include <QtCore/qdatastream.h>
11
12QT_BEGIN_NAMESPACE
13
14class QRemoteObjectRegistryPrivate : public QObjectPrivate
15{
16 Q_DECLARE_PUBLIC(QRemoteObjectRegistry)
17
18 QRemoteObjectSourceLocations sourceLocationsActualCalculation() const
19 {
20 return q_func()->propAsVariant(i: 0).value<QRemoteObjectSourceLocations>();
21 }
22 Q_OBJECT_COMPUTED_PROPERTY(QRemoteObjectRegistryPrivate, QRemoteObjectSourceLocations,
23 sourceLocations,
24 &QRemoteObjectRegistryPrivate::sourceLocationsActualCalculation)
25 QRemoteObjectSourceLocations hostedSources;
26};
27
28/*!
29 \class QRemoteObjectRegistry
30 \inmodule QtRemoteObjects
31 \brief A class holding information about \l {Source} objects available on the Qt Remote Objects network.
32
33 The Registry is a special Source/Replica pair held by a \l
34 {QRemoteObjectNode} {node} itself. It knows about all other \l {Source}s
35 available on the network, and simplifies the process of connecting to other
36 \l {QRemoteObjectNode} {node}s.
37*/
38QRemoteObjectRegistry::QRemoteObjectRegistry(QObject *parent)
39 : QRemoteObjectReplica(*new QRemoteObjectRegistryPrivate, parent)
40{
41 connect(sender: this, signal: &QRemoteObjectRegistry::stateChanged, context: this, slot: &QRemoteObjectRegistry::pushToRegistryIfNeeded);
42}
43
44QRemoteObjectRegistry::QRemoteObjectRegistry(QRemoteObjectNode *node, const QString &name, QObject *parent)
45 : QRemoteObjectReplica(*new QRemoteObjectRegistryPrivate, parent)
46{
47 connect(sender: this, signal: &QRemoteObjectRegistry::stateChanged, context: this, slot: &QRemoteObjectRegistry::pushToRegistryIfNeeded);
48 initializeNode(node, name);
49}
50
51/*!
52 \fn void QRemoteObjectRegistry::remoteObjectAdded(const QRemoteObjectSourceLocation &entry)
53
54 This signal is emitted whenever a new source location is added to the registry.
55
56 \a entry is a QRemoteObjectSourceLocation, a typedef for
57 QPair<QString, QRemoteObjectSourceLocationInfo>.
58
59 \sa remoteObjectRemoved()
60*/
61
62/*!
63 \fn void QRemoteObjectRegistry::remoteObjectRemoved(const QRemoteObjectSourceLocation &entry)
64
65 This signal is emitted whenever a Source location is removed from the Registry.
66
67 \a entry is a QRemoteObjectSourceLocation, a typedef for
68 QPair<QString, QRemoteObjectSourceLocationInfo>.
69
70 \sa remoteObjectAdded()
71*/
72
73/*!
74 \property QRemoteObjectRegistry::sourceLocations
75 \brief The set of sources known to the registry.
76
77 This property is a QRemoteObjectSourceLocations, which is a typedef for
78 QHash<QString, QRemoteObjectSourceLocationInfo>. Each known \l Source is
79 contained as a QString key in the hash, and the corresponding value for
80 that key is the QRemoteObjectSourceLocationInfo for the host node.
81*/
82
83/*!
84 Destructor for QRemoteObjectRegistry.
85*/
86QRemoteObjectRegistry::~QRemoteObjectRegistry()
87{}
88
89void QRemoteObjectRegistry::registerMetatypes()
90{
91 static bool initialized = false;
92 if (initialized)
93 return;
94 initialized = true;
95 qRegisterMetaType<QRemoteObjectSourceLocation>();
96 qRegisterMetaType<QRemoteObjectSourceLocations>();
97}
98
99void QRemoteObjectRegistry::initialize()
100{
101 QRemoteObjectRegistry::registerMetatypes();
102 QVariantList properties;
103 properties.reserve(asize: 3);
104 properties << QVariant::fromValue(value: QRemoteObjectSourceLocations());
105 properties << QVariant::fromValue(value: QRemoteObjectSourceLocation());
106 properties << QVariant::fromValue(value: QRemoteObjectSourceLocation());
107 setProperties(std::move(properties));
108}
109
110void QRemoteObjectRegistry::notifySourceLocationsChanged()
111{
112 d_func()->sourceLocations.notify();
113}
114
115/*!
116 Returns a QRemoteObjectSourceLocations object, which includes the name
117 and additional information of all sources known to the registry.
118*/
119QRemoteObjectSourceLocations QRemoteObjectRegistry::sourceLocations() const
120{
121 return d_func()->sourceLocations.value();
122}
123
124QBindable<QRemoteObjectSourceLocations> QRemoteObjectRegistry::bindableSourceLocations() const
125{
126 return &d_func()->sourceLocations;
127}
128
129/*!
130 \internal
131*/
132void QRemoteObjectRegistry::addSource(const QRemoteObjectSourceLocation &entry)
133{
134 Q_D(QRemoteObjectRegistry);
135 if (d->hostedSources.contains(key: entry.first)) {
136 qCWarning(QT_REMOTEOBJECT) << "Node warning: ignoring source" << entry.first
137 << "as this node already has a source by that name.";
138 return;
139 }
140 d->hostedSources.insert(key: entry.first, value: entry.second);
141 if (state() != QRemoteObjectReplica::State::Valid)
142 return;
143
144 if (sourceLocations().contains(key: entry.first)) {
145 qCWarning(QT_REMOTEOBJECT) << "Node warning: ignoring source" << entry.first
146 << "as another source (" << sourceLocations().value(key: entry.first)
147 << ") has already registered that name.";
148 return;
149 }
150 qCDebug(QT_REMOTEOBJECT) << "An entry was added to the registry - Sending to source" << entry.first << entry.second;
151 // This does not set any data to avoid a coherency problem between client and server
152 static int index = QRemoteObjectRegistry::staticMetaObject.indexOfMethod(method: "addSource(QRemoteObjectSourceLocation)");
153 QVariantList args;
154 args << QVariant::fromValue(value: entry);
155 send(call: QMetaObject::InvokeMetaMethod, index, args);
156}
157
158/*!
159 \internal
160*/
161void QRemoteObjectRegistry::removeSource(const QRemoteObjectSourceLocation &entry)
162{
163 Q_D(QRemoteObjectRegistry);
164 if (!d->hostedSources.contains(key: entry.first))
165 return;
166
167 d->hostedSources.remove(key: entry.first);
168 if (state() != QRemoteObjectReplica::State::Valid)
169 return;
170
171 qCDebug(QT_REMOTEOBJECT) << "An entry was removed from the registry - Sending to source" << entry.first << entry.second;
172 // This does not set any data to avoid a coherency problem between client and server
173 static int index = QRemoteObjectRegistry::staticMetaObject.indexOfMethod(method: "removeSource(QRemoteObjectSourceLocation)");
174 QVariantList args;
175 args << QVariant::fromValue(value: entry);
176 send(call: QMetaObject::InvokeMetaMethod, index, args);
177}
178
179/*!
180 \internal
181 This internal function supports the edge case where the \l Registry
182 is connected after \l Source objects are added to this \l Node, or
183 the connection to the \l Registry is lost. When connected/reconnected, this
184 function synchronizes local \l Source objects with the \l Registry.
185*/
186void QRemoteObjectRegistry::pushToRegistryIfNeeded()
187{
188 Q_D(QRemoteObjectRegistry);
189 if (state() != QRemoteObjectReplica::State::Valid)
190 return;
191
192 if (d->hostedSources.isEmpty())
193 return;
194
195 const auto &sourceLocs = sourceLocations();
196 for (auto it = d->hostedSources.begin(); it != d->hostedSources.end(); ) {
197 const QString &loc = it.key();
198 const auto sourceLocsIt = sourceLocs.constFind(key: loc);
199 if (sourceLocsIt != sourceLocs.cend()) {
200 qCWarning(QT_REMOTEOBJECT) << "Node warning: Ignoring Source" << loc << "as another source ("
201 << sourceLocsIt.value() << ") has already registered that name.";
202 it = d->hostedSources.erase(it);
203 } else {
204 static const int index = QRemoteObjectRegistry::staticMetaObject.indexOfMethod(method: "addSource(QRemoteObjectSourceLocation)");
205 QVariantList args{QVariant::fromValue(value: QRemoteObjectSourceLocation(loc, it.value()))};
206 send(call: QMetaObject::InvokeMetaMethod, index, args);
207 ++it;
208 }
209 }
210}
211
212QT_END_NAMESPACE
213

source code of qtremoteobjects/src/remoteobjects/qremoteobjectregistry.cpp