1/****************************************************************************
2**
3** Copyright (C) 2017 Ford Motor Company
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtRemoteObjects module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qremoteobjectregistry.h"
41#include "qremoteobjectreplica_p.h"
42
43#include <private/qobject_p.h>
44#include <QtCore/qset.h>
45#include <QtCore/qdatastream.h>
46
47QT_BEGIN_NAMESPACE
48
49class QRemoteObjectRegistryPrivate : public QObjectPrivate
50{
51 Q_DECLARE_PUBLIC(QRemoteObjectRegistry)
52
53 QRemoteObjectSourceLocations hostedSources;
54};
55
56/*!
57 \class QRemoteObjectRegistry
58 \inmodule QtRemoteObjects
59 \brief A class holding information about \l {Source} objects available on the Qt Remote Objects network.
60
61 The Registry is a special Source/Replica pair held by a \l
62 {QRemoteObjectNode} {node} itself. It knows about all other \l {Source}s
63 available on the network, and simplifies the process of connecting to other
64 \l {QRemoteObjectNode} {node}s.
65*/
66QRemoteObjectRegistry::QRemoteObjectRegistry(QObject *parent)
67 : QRemoteObjectReplica(*new QRemoteObjectRegistryPrivate, parent)
68{
69 connect(sender: this, signal: &QRemoteObjectRegistry::stateChanged, receiver: this, slot: &QRemoteObjectRegistry::pushToRegistryIfNeeded);
70}
71
72QRemoteObjectRegistry::QRemoteObjectRegistry(QRemoteObjectNode *node, const QString &name, QObject *parent)
73 : QRemoteObjectReplica(*new QRemoteObjectRegistryPrivate, parent)
74{
75 connect(sender: this, signal: &QRemoteObjectRegistry::stateChanged, receiver: this, slot: &QRemoteObjectRegistry::pushToRegistryIfNeeded);
76 initializeNode(node, name);
77}
78
79/*!
80 \fn void QRemoteObjectRegistry::remoteObjectAdded(const QRemoteObjectSourceLocation &entry)
81
82 This signal is emitted whenever a new source location is added to the registry.
83
84 \a entry is a QRemoteObjectSourceLocation, a typedef for QPair<QString, QUrl>.
85
86 \sa remoteObjectRemoved()
87*/
88
89/*!
90 \fn void QRemoteObjectRegistry::remoteObjectRemoved(const QRemoteObjectSourceLocation &entry)
91
92 This signal is emitted whenever a Source location is removed from the Registry.
93
94 \a entry is a QRemoteObjectSourceLocation, a typedef for QPair<QString, QUrl>.
95
96 \sa remoteObjectAdded()
97*/
98
99/*!
100 \property QRemoteObjectRegistry::sourceLocations
101 \brief The set of sources known to the registry.
102
103 This property is a QRemoteObjectSourceLocations, which is a typedef for QHash<QString, QUrl>. Each known \l Source is the QString key, while the url for the host node is the corresponding value for that key in the hash.
104*/
105
106/*!
107 Destructor for QRemoteObjectRegistry.
108*/
109QRemoteObjectRegistry::~QRemoteObjectRegistry()
110{}
111
112void QRemoteObjectRegistry::registerMetatypes()
113{
114 static bool initialized = false;
115 if (initialized)
116 return;
117 initialized = true;
118 qRegisterMetaType<QRemoteObjectSourceLocation>();
119 qRegisterMetaTypeStreamOperators<QRemoteObjectSourceLocation>();
120 qRegisterMetaType<QRemoteObjectSourceLocations>();
121 qRegisterMetaTypeStreamOperators<QRemoteObjectSourceLocations>();
122}
123
124void QRemoteObjectRegistry::initialize()
125{
126 QRemoteObjectRegistry::registerMetatypes();
127 QVariantList properties;
128 properties.reserve(alloc: 3);
129 properties << QVariant::fromValue(value: QRemoteObjectSourceLocations());
130 properties << QVariant::fromValue(value: QRemoteObjectSourceLocation());
131 properties << QVariant::fromValue(value: QRemoteObjectSourceLocation());
132 setProperties(properties);
133}
134
135/*!
136 Returns a QRemoteObjectSourceLocations object, which includes the name
137 and additional information of all sources known to the registry.
138*/
139QRemoteObjectSourceLocations QRemoteObjectRegistry::sourceLocations() const
140{
141 return propAsVariant(i: 0).value<QRemoteObjectSourceLocations>();
142}
143
144/*!
145 \internal
146*/
147void QRemoteObjectRegistry::addSource(const QRemoteObjectSourceLocation &entry)
148{
149 Q_D(QRemoteObjectRegistry);
150 if (d->hostedSources.contains(akey: entry.first)) {
151 qCWarning(QT_REMOTEOBJECT) << "Node warning: ignoring source" << entry.first
152 << "as this node already has a source by that name.";
153 return;
154 }
155 d->hostedSources.insert(akey: entry.first, avalue: entry.second);
156 if (state() != QRemoteObjectReplica::State::Valid)
157 return;
158
159 if (sourceLocations().contains(akey: entry.first)) {
160 qCWarning(QT_REMOTEOBJECT) << "Node warning: ignoring source" << entry.first
161 << "as another source (" << sourceLocations().value(akey: entry.first)
162 << ") has already registered that name.";
163 return;
164 }
165 qCDebug(QT_REMOTEOBJECT) << "An entry was added to the registry - Sending to source" << entry.first << entry.second;
166 // This does not set any data to avoid a coherency problem between client and server
167 static int index = QRemoteObjectRegistry::staticMetaObject.indexOfMethod(method: "addSource(QRemoteObjectSourceLocation)");
168 QVariantList args;
169 args << QVariant::fromValue(value: entry);
170 send(call: QMetaObject::InvokeMetaMethod, index, args);
171}
172
173/*!
174 \internal
175*/
176void QRemoteObjectRegistry::removeSource(const QRemoteObjectSourceLocation &entry)
177{
178 Q_D(QRemoteObjectRegistry);
179 if (!d->hostedSources.contains(akey: entry.first))
180 return;
181
182 d->hostedSources.remove(akey: entry.first);
183 if (state() != QRemoteObjectReplica::State::Valid)
184 return;
185
186 qCDebug(QT_REMOTEOBJECT) << "An entry was removed from the registry - Sending to source" << entry.first << entry.second;
187 // This does not set any data to avoid a coherency problem between client and server
188 static int index = QRemoteObjectRegistry::staticMetaObject.indexOfMethod(method: "removeSource(QRemoteObjectSourceLocation)");
189 QVariantList args;
190 args << QVariant::fromValue(value: entry);
191 send(call: QMetaObject::InvokeMetaMethod, index, args);
192}
193
194/*!
195 \internal
196 This internal function supports the edge case where the \l Registry
197 is connected after \l Source objects are added to this \l Node, or
198 the connection to the \l Registry is lost. When connected/reconnected, this
199 function synchronizes local \l Source objects with the \l Registry.
200*/
201void QRemoteObjectRegistry::pushToRegistryIfNeeded()
202{
203 Q_D(QRemoteObjectRegistry);
204 if (state() != QRemoteObjectReplica::State::Valid)
205 return;
206
207 if (d->hostedSources.isEmpty())
208 return;
209
210 const auto &sourceLocs = sourceLocations();
211 for (auto it = d->hostedSources.begin(); it != d->hostedSources.end(); ) {
212 const QString &loc = it.key();
213 const auto sourceLocsIt = sourceLocs.constFind(akey: loc);
214 if (sourceLocsIt != sourceLocs.cend()) {
215 qCWarning(QT_REMOTEOBJECT) << "Node warning: Ignoring Source" << loc << "as another source ("
216 << sourceLocsIt.value() << ") has already registered that name.";
217 it = d->hostedSources.erase(it);
218 } else {
219 static const int index = QRemoteObjectRegistry::staticMetaObject.indexOfMethod(method: "addSource(QRemoteObjectSourceLocation)");
220 QVariantList args{QVariant::fromValue(value: QRemoteObjectSourceLocation(loc, it.value()))};
221 send(call: QMetaObject::InvokeMetaMethod, index, args);
222 ++it;
223 }
224 }
225}
226
227QT_END_NAMESPACE
228

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