7#include "connector_p.h"
10#include "../shared/connectorutils_p.h"
11#include "../shared/unifiedpush-constants.h"
15#include <QStandardPaths>
20ConnectorPrivate::ConnectorPrivate(
Connector *qq)
27ConnectorPrivate::~ConnectorPrivate()
34 qCDebug(
Log) << token << message << messageIdentifier << m_contentEnc.hasKeys();
35 if (token != m_token) {
36 qCWarning(
Log) <<
"Got message for a different token??";
39 if (m_contentEnc.hasKeys()) {
40 const auto decrypted = m_contentEnc.decrypt(message);
41 qCDebug(
Log) << token << decrypted;
42 if (!decrypted.isEmpty()) {
43 Q_EMIT q->messageReceived(decrypted);
48 Q_EMIT q->messageReceived(message);
51QVariantMap ConnectorPrivate::Message(
const QVariantMap &args)
53 const auto token = args.value(UP_ARG_TOKEN).toString();
54 const auto message = args.value(UP_ARG_MESSAGE).toByteArray();
55 const auto id = args.value(UP_ARG_MESSAGE_IDENTIFIER).toString();
60 r.insert(UP_ARG_MESSAGE_IDENTIFIER,
id);
65void ConnectorPrivate::NewEndpoint(
const QString &token,
const QString &endpoint)
67 qCDebug(
Log) << token << endpoint;
68 if (token != m_token) {
69 qCWarning(
Log) <<
"Got new endpoint for a different token??";
74 QString actuallyWorkingEndpoint(endpoint);
77 if (m_endpoint != actuallyWorkingEndpoint) {
78 m_endpoint = actuallyWorkingEndpoint;
79 Q_EMIT q->endpointChanged(m_endpoint);
85QVariantMap ConnectorPrivate::NewEndpoint(
const QVariantMap &args)
87 const auto token = args.value(UP_ARG_TOKEN).toString();
88 const auto endpoint = args.value(UP_ARG_ENDPOINT).toString();
89 NewEndpoint(token, endpoint);
93void ConnectorPrivate::Unregistered(
const QString &token)
95 qCDebug(
Log) << token;
101 Q_EMIT q->endpointChanged(m_endpoint);
103 qCDebug(
Log) <<
"Removing" << stateFile() << res;
108 else if (token == m_token) {
110 Q_EMIT q->endpointChanged(m_endpoint);
116 m_currentCommand = Command::None;
118 processNextCommand();
121QVariantMap ConnectorPrivate::Unregistered(
const QVariantMap &args)
123 const auto token = args.value(UP_ARG_TOKEN).toString();
128QString ConnectorPrivate::stateFile()
const
133void ConnectorPrivate::loadState()
136 settings.beginGroup(
"Client");
137 m_token = settings.value(
"Token").toString();
138 m_endpoint = settings.value(
"Endpoint").toString();
139 m_description = settings.value(
"Description").toString();
140 m_vapidRequired = settings.value(
"VapidRequired",
false).toBool();
141 m_vapidPublicKey = settings.value(
"VapidPublicKey").toString();
143 const auto pubKey = settings.value(
"ContentEncryptionPublicKey").toByteArray();
144 const auto privKey = settings.value(
"ContentEncryptionPrivateKey").toByteArray();
145 const auto authSec = settings.value(
"contentEncryptionAuthSecret").toByteArray();
146 if (!pubKey.isEmpty() && !privKey.isEmpty() && !authSec.isEmpty()) {
147 m_contentEnc = ContentEncryption(pubKey, privKey, authSec);
151void ConnectorPrivate::storeState()
const
154 settings.beginGroup(
"Client");
155 settings.setValue(
"Token", m_token);
156 settings.setValue(
"Endpoint", m_endpoint);
157 settings.setValue(
"Description", m_description);
158 settings.setValue(
"VapidRequired", m_vapidRequired);
159 settings.setValue(
"VapidPublicKey", m_vapidPublicKey);
161 if (m_contentEnc.hasKeys()) {
162 settings.setValue(
"ContentEncryptionPublicKey", m_contentEnc.publicKey());
163 settings.setValue(
"ContentEncryptionPrivateKey", m_contentEnc.privateKey());
164 settings.setValue(
"contentEncryptionAuthSecret", m_contentEnc.authSecret());
168void ConnectorPrivate::setDistributor(
const QString &distServiceName)
170 if (distServiceName.
isEmpty()) {
171 qCWarning(
Log) <<
"No UnifiedPush distributor found.";
176 doSetDistributor(distServiceName);
177 qCDebug(
Log) <<
"Selected distributor" << distServiceName;
180 if (!m_token.isEmpty()) {
181 q->registerClient(m_description);
185void ConnectorPrivate::registrationFailed(
const QString &token,
const QString &reason)
187 qCDebug(
Log) << token << reason;
188 if (token != m_token) {
198 qCDebug(
Log) << state;
199 if (m_state == state) {
204 Q_EMIT q->stateChanged(m_state);
207void ConnectorPrivate::addCommand(ConnectorPrivate::Command cmd)
210 if (!m_commandQueue.empty()) {
211 if (m_commandQueue.back() == cmd) {
215 m_commandQueue.pop_back();
218 }
else if (m_currentCommand == cmd) {
222 m_commandQueue.push_back(cmd);
223 processNextCommand();
226bool ConnectorPrivate::isNextCommandReady()
const
228 assert(!m_commandQueue.empty());
230 if (m_commandQueue.front() == Command::Register) {
231 return !m_vapidRequired || !m_vapidPublicKey.isEmpty();
236void ConnectorPrivate::processNextCommand()
238 if (m_currentCommand != Command::None || !hasDistributor() || m_commandQueue.empty() || !isNextCommandReady()) {
242 m_currentCommand = m_commandQueue.front();
243 m_commandQueue.pop_front();
245 switch (m_currentCommand) {
248 case Command::Register:
251 m_currentCommand = Command::None;
255 if (m_token.isEmpty()) {
258 qCDebug(
Log) <<
"Registering";
264 m_currentCommand = Command::None;
267 qCDebug(
Log) <<
"Unregistering";
272 processNextCommand();
275void ConnectorPrivate::ensureKeys()
277 if (m_contentEnc.hasKeys()) {
280 m_contentEnc = ContentEncryption::generateKeys();
287 , d(new ConnectorPrivate(this))
289 d->m_serviceName = serviceName;
290 if (d->m_serviceName.isEmpty()) {
291 qCWarning(Log) <<
"empty D-Bus service name!";
296 d->setDistributor(ConnectorUtils::selectDistributor());
299Connector::~Connector() =
default;
303 return d->m_endpoint;
308 qCDebug(
Log) << d->m_state;
309 d->m_description = description;
310 d->addCommand(ConnectorPrivate::Command::Register);
315 qCDebug(
Log) << d->m_state;
316 d->addCommand(ConnectorPrivate::Command::Unregister);
326 return d->m_vapidPublicKey;
331 if (d->m_vapidPublicKey == vapidPublicKey) {
335 d->m_vapidPublicKey = vapidPublicKey;
339 if (!d->m_token.isEmpty()) {
340 d->addCommand(ConnectorPrivate::Command::Unregister);
341 d->addCommand(ConnectorPrivate::Command::None);
342 d->addCommand(ConnectorPrivate::Command::Register);
344 d->processNextCommand();
348bool Connector::vapidPublicKeyRequired()
const
350 return d->m_vapidRequired;
355 if (d->m_vapidRequired == vapidRequired) {
359 d->m_vapidRequired = vapidRequired;
361 d->processNextCommand();
367 return d->m_contentEnc.publicKey();
373 return d->m_contentEnc.authSecret();
376#include "moc_connector.cpp"
377#include "moc_connector_p.cpp"
@ Unregister
unregistration requested by client
Client connector to UnifiedPush.
Connector(const QString &serviceName, QObject *parent=nullptr)
Create a new connector instance.
void setVapidPublicKeyRequired(bool vapidRequired)
Sets whether a Voluntary Application Server Identification (VAPID) public key is required before regi...
void vapidPublicKeyChanged()
Emitted when the VAPID public key changed.
QByteArray contentEncryptionPublicKey() const
Content encryption user agent public key.
void unregisterClient()
Unregister this client.
QByteArray contentEncryptionAuthSecret() const
Content encryption authentication secret.
@ Error
Any other error condition.
@ NoDistributor
Connector cannot find a UnifiedPush distributor to register at.
@ Registering
Connector is registering with the push provider.
@ Registered
Connector is registered and thus operational.
@ Unregistered
Connector is not yet registered, or explicitly unregistered.
void vapidPublicKeyRequiredChanged()
Emitted when the VAPID public key required property changed.
void registerClient(const QString &description)
Register this client.
void setVapidPublicKey(const QString &vapidPublicKey)
Sets the Voluntary Application Server Identification (VAPID) public key of the corresponding applicat...
A received push notification message.
Client-side integration with UnifiedPush.
QObject * parent() const const
QString writableLocation(StandardLocation type)
bool isEmpty() const const
QString toString(StringFormat mode) const const