diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/CMakeLists.txt | 28 | ||||
-rw-r--r-- | core/callmessage.cpp | 55 | ||||
-rw-r--r-- | core/callmessage.h | 52 | ||||
-rw-r--r-- | core/eventmessage.cpp | 67 | ||||
-rw-r--r-- | core/eventmessage.h | 61 | ||||
-rw-r--r-- | core/message.cpp | 79 | ||||
-rw-r--r-- | core/message.h | 71 | ||||
-rw-r--r-- | core/messageengine.cpp | 90 | ||||
-rw-r--r-- | core/messageengine.h | 55 | ||||
-rw-r--r-- | core/messageenginefactory.cpp | 39 | ||||
-rw-r--r-- | core/messageenginefactory.h | 41 | ||||
-rw-r--r-- | core/messagefactory.cpp | 39 | ||||
-rw-r--r-- | core/messagefactory.h | 42 | ||||
-rw-r--r-- | core/qtappfw-core.pc.in | 12 | ||||
-rw-r--r-- | core/responsemessage.cpp | 101 | ||||
-rw-r--r-- | core/responsemessage.h | 88 |
16 files changed, 920 insertions, 0 deletions
diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt new file mode 100644 index 0000000..3102f3b --- /dev/null +++ b/core/CMakeLists.txt @@ -0,0 +1,28 @@ + +CONFIGURE_FILE("qtappfw-core.pc.in" "qtappfw-core.pc" @ONLY) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/qtappfw-core.pc + DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/pkgconfig) + +add_library(qtappfw-core SHARED message.cpp + messagefactory.cpp + messageengine.cpp + messageenginefactory.cpp + responsemessage.cpp + callmessage.cpp + eventmessage.cpp) + +target_include_directories(qtappfw-core PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}") +target_include_directories(qtappfw-core PUBLIC "${CMAKE_INSTALL_INCLUDEDIR}") + +target_link_libraries(qtappfw-core Qt5::WebSockets) + +set_target_properties(qtappfw-core PROPERTIES + VERSION ${PROJECT_VERSION} + SOVERSION 1 + PUBLIC_HEADER "message.h;messagefactory.h;messageengine.h;messageenginefactory.h;responsemessage.h;callmessage.h;eventmessage.h") + + +install(TARGETS qtappfw-core + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/qtappfw-core) + diff --git a/core/callmessage.cpp b/core/callmessage.cpp new file mode 100644 index 0000000..1dfa72e --- /dev/null +++ b/core/callmessage.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2020 Konsulko Group + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <QDebug> +#include <QJsonArray> +#include <QJsonDocument> +#include <QJsonValue> + +#include "callmessage.h" +#include "message.h" + + +bool CallMessage::createRequest(QString api, QString verb, QJsonValue parameter) +{ + if (!m_request.isEmpty()){ + qWarning("Message instance has already been used. Cannot send another request."); + return false; + } + + m_request["msgid"] = static_cast<unsigned int>(MessageId::Call); + m_request["callid"] = 0; + m_request["api"] = api; + m_request["verb"] = verb; + m_request["parameter"] = parameter; + + m_init = true; + + return m_init; +} + +QByteArray CallMessage::serialize(QJsonDocument::JsonFormat format) +{ + QJsonArray array; + array.append(m_request["msgid"].toInt()); + array.append(m_request["callid"].toInt()); + array.append(m_request["api"].toString() + "/" + m_request["verb"].toString()); + array.append(m_request["parameter"].toJsonValue()); + + m_jdoc.setArray(array); + + return m_jdoc.toJson(format).data(); +} diff --git a/core/callmessage.h b/core/callmessage.h new file mode 100644 index 0000000..d08024e --- /dev/null +++ b/core/callmessage.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2020 Konsulko Group + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CALLMESSAGE_H +#define CALLMESSAGE_H + +#include "message.h" + + +class CallMessage : public Message +{ + public: + bool createRequest(QString api, QString verb, QJsonValue parameter = "None"); + + bool isEvent() override + { + return false; + } + + bool isReply() override + { + return false; + } + + void updateCallId(unsigned int id) override + { + m_request["callid"] = qint32(id); + } + + QByteArray serialize(QJsonDocument::JsonFormat format = QJsonDocument::Compact) override; + + private: + QMap<QString, QVariant> m_request; + + CallMessage() = default; + friend class MessageFactory; +}; + +#endif // CALLMESSAGE_H diff --git a/core/eventmessage.cpp b/core/eventmessage.cpp new file mode 100644 index 0000000..818830f --- /dev/null +++ b/core/eventmessage.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2020 Konsulko Group + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <QDebug> +#include <QJsonArray> +#include <QJsonDocument> +#include <QJsonObject> +#include <QJsonValue> + +#include "eventmessage.h" + +EventMessage::EventMessage(QJsonDocument content): Message() +{ + QJsonArray msg = content.array(); + if (!msg[2].isObject()) { + qWarning("Invalid appfw payload: no JSON object"); + return; + } + + //deserialize: + QJsonObject payload = msg[2].toObject(); + + auto data_iter = payload.find("data"); + m_event_data = data_iter.value().toObject(); + + auto event_iter = payload.find("event"); + auto event_string = event_iter.value().toString(); + if (event_string.isEmpty()) { + qWarning("Invalid appfw event message: empty event name"); + return; + } + QStringList event_strings = event_string.split(QRegExp("/")); + if (event_strings.size() != 2) { + qWarning("Invalid appfw event message: malformed event name"); + return; + } + m_event_api = event_strings[0]; + m_event_name = event_strings[1]; + m_init = true; +} + +QByteArray EventMessage::serialize(QJsonDocument::JsonFormat format) +{ + QJsonArray array; + array.append(static_cast<int>(MessageId::Event)); + array.append(0); //unused field + array.append(m_event_api + "/" + m_event_name); + array.append(m_event_data); + + QJsonDocument jdoc; + jdoc.setArray(array); + + return jdoc.toJson(format).data(); +} diff --git a/core/eventmessage.h b/core/eventmessage.h new file mode 100644 index 0000000..133574c --- /dev/null +++ b/core/eventmessage.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2020 Konsulko Group + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef EVENTMESSAGE_H +#define EVENTMESSAGE_H + +#include "message.h" + + +class EventMessage : public Message +{ + public: + inline QString eventApi() const + { + return m_event_api; + } + + inline QString eventName() const + { + return m_event_name; + } + + inline QJsonObject eventData() const + { + return m_event_data; + } + + bool isEvent() override + { + return true; + } + + bool isReply() override + { + return false; + } + + QByteArray serialize(QJsonDocument::JsonFormat format = QJsonDocument::Compact) override; + + private: + QString m_event_api, m_event_name; + QJsonObject m_event_data; + + explicit EventMessage(QJsonDocument data); + friend class MessageFactory; +}; + +#endif // EVENTMESSAGE_H diff --git a/core/message.cpp b/core/message.cpp new file mode 100644 index 0000000..1865f14 --- /dev/null +++ b/core/message.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2017-2020 Konsulko Group + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <QDebug> +#include <QJsonArray> +#include <QJsonDocument> +#include <QWebSocket> + +#include "message.h" + +MessageId Message::isValid(QJsonDocument candidate) +{ + MessageId id = MessageId::Invalid; + + // Validate message is array + if (!candidate.isArray()) { + qWarning("Invalid appfw message: not an array"); + return id; + } + QJsonArray msg = candidate.array(); + + // Validate array is proper length + if ((msg.size() < 3) || (msg.size() > 4)) { + qWarning("Invalid appfw message: invalid array size"); + return id; + } + + // Validate msgid type + double msgid; + if (msg[0].isDouble()) { + msgid = msg[0].toDouble(); + } else { + qWarning("Invalid appfw message: invalid msgid type"); + return id; + } + + // Validate msgid element + if ((msgid >= static_cast<double>(MessageId::Call)) && (msgid <= static_cast<double>(MessageId::Event))) + id = static_cast<MessageId>(msgid); + + return id; +} + +Message::Message() + : m_init(false) +{ +} + +QByteArray Message::serialize(QJsonDocument::JsonFormat format) +{ + QByteArray dummy; + return dummy; + } + +QByteArray Message::send(QWebSocket& transport, unsigned int id) +{ + QByteArray blob; + qint64 size = 0; + updateCallId(id); + if (m_init) + blob = serialize().data(); + if (!blob.isEmpty()) + size = transport.sendTextMessage(blob); + + return blob; +} diff --git a/core/message.h b/core/message.h new file mode 100644 index 0000000..acbbefd --- /dev/null +++ b/core/message.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2017-2020 Konsulko Group + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MESSAGE_H +#define MESSAGE_H + +#include <memory> +#include <QObject> +#include <QMap> +#include <QVariant> +#include <QJsonDocument> +#include <QJsonObject> + +enum class MessageId { + Invalid = 0, + Call = 2, + RetOk = 3, + RetErr = 4, + Event = 5, +}; + +class QWebSocket; + +class Message +{ + public: + Message(); + virtual bool setAdditionalData(QByteArray data) + { + return false; + } + QByteArray send(QWebSocket& transport, unsigned int callid); + + inline bool isComplete() const + { + return m_init; + } + + virtual bool getCallId(unsigned int *id) const + { + return false; + } + + static MessageId isValid(QJsonDocument ); + + virtual bool isEvent() = 0; + virtual bool isReply() = 0; + + protected: + virtual void updateCallId(unsigned int id) {}; + virtual QByteArray serialize(QJsonDocument::JsonFormat format = QJsonDocument::Compact); + + bool m_init; + QJsonDocument m_jdoc; +}; +Q_DECLARE_METATYPE(std::shared_ptr<Message>) + +#endif // MESSAGE_H diff --git a/core/messageengine.cpp b/core/messageengine.cpp new file mode 100644 index 0000000..42fe95b --- /dev/null +++ b/core/messageengine.cpp @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2017-2020 Konsulko Group + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <QJsonArray> +#include <QDebug> + +#include "message.h" +#include "messagefactory.h" +#include "messageengine.h" + + +MessageEngine::MessageEngine(const QUrl &url) : + QObject(Q_NULLPTR), + m_callid(0), + m_url(url) +{ + connect(&m_websocket, &QWebSocket::connected, this, &MessageEngine::onConnected); + connect(&m_websocket, &QWebSocket::disconnected, this, &MessageEngine::onDisconnected); + + m_websocket.open(url); +} + +bool MessageEngine::sendMessage(std::unique_ptr<Message> msg) +{ + if (!msg) + return false; + + unsigned int callid = m_callid++; + QByteArray forkeeps = msg->send(m_websocket, callid); + if (forkeeps.isEmpty()) + return false; + + std::lock_guard<std::mutex> localguard(m_mutex); + m_calls.insert(callid, forkeeps); + + return true; +} + +void MessageEngine::onConnected() +{ + connect(&m_websocket, &QWebSocket::textMessageReceived, this, &MessageEngine::onTextMessageReceived); + emit connected(); +} + +void MessageEngine::onDisconnected() +{ + disconnect(&m_websocket, &QWebSocket::textMessageReceived, this, &MessageEngine::onTextMessageReceived); + emit disconnected(); +} + +void MessageEngine::onTextMessageReceived(QString jsonStr) +{ + jsonStr = jsonStr.simplified(); + QJsonDocument jdoc(QJsonDocument::fromJson(jsonStr.toUtf8())); + if (jdoc.isEmpty()) { + qWarning() << "Received invalid JSON: empty appfw message"; + return; + } + + MessageId id = Message::isValid(jdoc); + if (id == MessageId::Invalid) { + qWarning() << "Received unknown message, discarding"; + return; + } + + std::shared_ptr<Message> message = MessageFactory::getInstance().createInboundMessage(id, jdoc); + + unsigned int callid; + if (message->isReply() && message->getCallId(&callid)) { + message->setAdditionalData(m_calls[callid]); + std::lock_guard<std::mutex> localguard(m_mutex); + m_calls.remove(callid); + } + + if (message->isComplete()) + emit messageReceived(message); +} diff --git a/core/messageengine.h b/core/messageengine.h new file mode 100644 index 0000000..12aa5e9 --- /dev/null +++ b/core/messageengine.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2017-2020 Konsulko Group + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MESSAGEENGINE_H +#define MESSAGEENGINE_H + +#include <memory> +#include <atomic> +#include <mutex> +#include <QUrl> +#include <QWebSocket> + +#include "message.h" + +class MessageEngine : public QObject +{ + Q_OBJECT + public: + bool sendMessage(std::unique_ptr<Message> message); + + Q_SIGNALS: + void disconnected(); + void connected(); + void messageReceived(std::shared_ptr<Message> message); + + private Q_SLOTS: + void onConnected(); + void onDisconnected(); + void onTextMessageReceived(QString message); + + private: + QWebSocket m_websocket; + std::mutex m_mutex; + QMap<qint32, QByteArray> m_calls; + QUrl m_url; + std::atomic<unsigned int> m_callid; + + explicit MessageEngine(const QUrl &url); + friend class MessageEngineFactory; +}; + +#endif // MESSAGEENGINE_H diff --git a/core/messageenginefactory.cpp b/core/messageenginefactory.cpp new file mode 100644 index 0000000..04fb741 --- /dev/null +++ b/core/messageenginefactory.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 Konsulko Group + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include <unordered_map> +#include <mutex> +#include <QDebug> +#include <QUrl> +#include "messageenginefactory.h" +#include "messageengine.h" + +std::shared_ptr<MessageEngine> MessageEngineFactory::getMessageEngine(const QUrl& url) +{ + static std::unordered_map<QString, std::shared_ptr<MessageEngine>> lut; + static std::mutex m; + + std::lock_guard<std::mutex> localguard(m); + auto urlstr = url.toString(); + auto pme = lut[urlstr]; + if (!pme){ + pme = std::shared_ptr<MessageEngine>{new MessageEngine(url)}; + lut[urlstr] = pme; + } + + return pme; +} diff --git a/core/messageenginefactory.h b/core/messageenginefactory.h new file mode 100644 index 0000000..1ce107b --- /dev/null +++ b/core/messageenginefactory.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2020 Konsulko Group + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MESSAGEENGINEFACTORY_H +#define MESSAGEENGINEFACTORY_H + +#include <memory> + +class MessageEngine; +class QUrl; + + +class MessageEngineFactory { + public: + static MessageEngineFactory& getInstance() { + static MessageEngineFactory instance; + return instance; + } + std::shared_ptr<MessageEngine> getMessageEngine(const QUrl &ur); + MessageEngineFactory(MessageEngineFactory const&) = delete; + void operator=(MessageEngineFactory const&) = delete; + + private: + MessageEngineFactory() = default; + ~MessageEngineFactory() = default; +}; + +#endif // MESSAGENGINEEFACTORY_H diff --git a/core/messagefactory.cpp b/core/messagefactory.cpp new file mode 100644 index 0000000..6740e25 --- /dev/null +++ b/core/messagefactory.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 Konsulko Group + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "messagefactory.h" +#include "message.h" +#include "responsemessage.h" +#include "eventmessage.h" +#include "callmessage.h" + +std::unique_ptr<Message> MessageFactory::createInboundMessage(MessageId id, QJsonDocument data) +{ + std::unique_ptr<Message> msg(nullptr); + if ((id == MessageId::RetOk) || (id == MessageId::RetErr)) + msg.reset(new ResponseMessage(data)); + else if (id == MessageId::Event) + msg.reset(new EventMessage(data)); + return msg; +} + +std::unique_ptr<Message> MessageFactory::createOutboundMessage(MessageId id) +{ + std::unique_ptr<Message> msg(nullptr); + if (id == MessageId::Call) + msg.reset(new CallMessage()); + return msg; +} diff --git a/core/messagefactory.h b/core/messagefactory.h new file mode 100644 index 0000000..f826483 --- /dev/null +++ b/core/messagefactory.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2020 Konsulko Group + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MESSAGEFACTORY_H +#define MESSAGEFACTORY_H + +#include <memory> +#include <QJsonDocument> + +class Message; +enum class MessageId; + +class MessageFactory { + public: + static MessageFactory& getInstance() { + static MessageFactory instance; + return instance; + } + std::unique_ptr<Message> createInboundMessage(MessageId id, QJsonDocument content); + std::unique_ptr<Message> createOutboundMessage(MessageId); + MessageFactory(MessageFactory const&) = delete; + void operator=(MessageFactory const&) = delete; + + private: + MessageFactory() = default; + ~MessageFactory() = default; +}; + +#endif // MESSAGEFACTORY_H diff --git a/core/qtappfw-core.pc.in b/core/qtappfw-core.pc.in new file mode 100644 index 0000000..bfef2e0 --- /dev/null +++ b/core/qtappfw-core.pc.in @@ -0,0 +1,12 @@ +prefix=@DEST_DIR@ +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: qtappfw-core +Description: Library wrapping AGL AppFW messages and bindings in Qt objects +Version: 1.0.0 + +Requires: Qt5WebSockets +Libs: -L${libdir} -lqtappfw-core +Cflags: -I${includedir}/qtappfw-core diff --git a/core/responsemessage.cpp b/core/responsemessage.cpp new file mode 100644 index 0000000..9f8e6f2 --- /dev/null +++ b/core/responsemessage.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2018-2020 Konsulko Group + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <QDebug> +#include <QJsonArray> +#include <QJsonDocument> +#include <QJsonObject> +#include <QJsonValue> + +#include "responsemessage.h" + + +ResponseMessage::ResponseMessage(QJsonDocument content) +{ + m_jdoc = content; + QJsonArray msg = content.array(); + if (!msg[2].isObject()) { + qWarning("Invalid appfw payload: no JSON object"); + return; + } + + //deserialize: + auto callid = msg[1].toString().toInt(); + QJsonObject payload = msg[2].toObject(); + + auto request_iter = payload.find("request"); + auto request = request_iter.value().toObject(); + if (request.empty()) { + qWarning("Invalid appfw reply message: empty request data"); + return; + } + + auto status_iter = request.find("status"); + auto info_iter = request.find("info"); + auto response_iter = payload.find("response"); + auto response = response_iter.value().toObject(); + m_reply_status = status_iter.value().toString(); + m_reply_info = info_iter.value().toString(); + m_reply_data = response; + m_reply_callid = callid; + m_init = false; //not complete yet, missing matching request data +} + +bool ResponseMessage::setAdditionalData(QByteArray data) +{ + QJsonDocument jdoc(QJsonDocument::fromJson(data)); + if (!jdoc.isArray()) { + qWarning("Invalid data: not an array"); + return false; + } + + QJsonArray content = jdoc.array(); + if (content.size() != 4) { + qWarning("Invalid data: invalid array size"); + return false; + } + + QStringList api_str_list = content[2].toString().split(QRegExp("/")); + m_request["msgid"] = content.at(0); + m_request["callid"] = content.at(1); + m_request["api"] = api_str_list[0]; + m_request["verb"] = api_str_list[1]; + m_request["parameter"] = content.at(3); + m_init = true; + return true; +} + +bool ResponseMessage::copyCallId(unsigned int *id) +{ + *id = m_reply_callid; + return true; +} + +QByteArray ResponseMessage::serialize(QJsonDocument::JsonFormat format) +{ + QJsonArray array; + (m_reply_status == "failed")? + array.append(static_cast<int>(MessageId::RetErr)) : + array.append(static_cast<int>(MessageId::RetOk)); + array.append(static_cast<int>(m_reply_callid)); + array.append(m_request["api"].toString() + "/" + m_request["verb"].toString()); + array.append(m_reply_data); + + QJsonDocument jdoc; + jdoc.setArray(array); + + return jdoc.toJson(format).data(); +} diff --git a/core/responsemessage.h b/core/responsemessage.h new file mode 100644 index 0000000..af6bda5 --- /dev/null +++ b/core/responsemessage.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2018-2020 Konsulko Group + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RESPONSEMESSAGE_H +#define RESPONSEMESSAGE_H + + +#include "message.h" + +class ResponseMessage : public Message +{ + + + public: + inline QString requestApi() const + { + return m_request["api"].toString(); + } + + inline QString requestVerb() const + { + return m_request["verb"].toString(); + } + + inline QVariantMap requestParameters() const + { + return m_request["parameter"].toMap(); + } + + inline QString replyStatus() const + { + return m_reply_status; + } + + inline QString replyInfo() const + { + return m_reply_info; + } + + inline QJsonObject replyData() const + { + return m_reply_data; + } + + bool getCallId(unsigned int *id) const override + { + *id = m_reply_callid; + return true; + } + bool isEvent() override + { + return false; + } + + bool isReply() override + { + return true; + } + + bool setAdditionalData(QByteArray data) override; + bool copyCallId(unsigned int *id); + + QByteArray serialize(QJsonDocument::JsonFormat format = QJsonDocument::Compact) override; + + private: + QString m_reply_info, m_reply_status, m_reply_uuid; + unsigned int m_reply_callid; + QJsonObject m_reply_data; + QMap<QString, QVariant> m_request; + + explicit ResponseMessage(QJsonDocument data); + friend class MessageFactory; +}; + +#endif // RESPONSEMESSAGE_H |