// SPDX-License-Identifier: LGPL-3.0-or-later /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * nymea-remoteproxy * Tunnel proxy server for the nymea remote access * * Copyright (C) 2013 - 2024, nymea GmbH * Copyright (C) 2024 - 2025, chargebyte austria GmbH * * This file is part of nymea-remoteproxy. * * nymea-remoteproxy is free software: you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation, either version 3 * of the License, or (at your option) any later version. * * nymea-remoteproxy is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with nymea-remoteproxy. If not, see . * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "slipdataprocessor.h" #include QByteArray SlipDataProcessor::deserializeData(const QByteArray &data) { QByteArray deserializedData; // Parse serial data bool escaped = false; for (int i = 0; i < data.length(); i++) { quint8 byte = static_cast(data.at(i)); if (escaped) { if (byte == ProtocolByteTransposedEnd) { deserializedData.append(static_cast(ProtocolByteEnd)); } else if (byte == ProtocolByteTransposedEsc) { deserializedData.append(static_cast(ProtocolByteEsc)); } else { qWarning() << "Error while deserializing data. Escape character received but the escaped character was not recognized."; return QByteArray(); } escaped = false; continue; } // If escape byte, the next byte has to be a modified byte if (byte == ProtocolByteEsc) { escaped = true; } else if (byte == ProtocolByteEnd) { // We are done...lets skip the rest of the data since we got the end byte break; } else { deserializedData.append(static_cast(byte)); } } return deserializedData; } QByteArray SlipDataProcessor::serializeData(const QByteArray &data) { QByteArray serializedData; #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) QDataStream stream(&serializedData, QDataStream::WriteOnly); #else QDataStream stream(&serializedData, QIODevice::WriteOnly); #endif // stream << static_cast(ProtocolByteEnd); for (int i = 0; i < data.length(); i++) { quint8 byte = static_cast(data.at(i)); switch (byte) { case ProtocolByteEnd: stream << static_cast(ProtocolByteEsc); stream << static_cast(ProtocolByteTransposedEnd); break; case ProtocolByteEsc: stream << static_cast(ProtocolByteEsc); stream << static_cast(ProtocolByteTransposedEsc); break; default: stream << byte; break; } } // Add the protocol end byte stream << static_cast(ProtocolByteEnd); return serializedData; } SlipDataProcessor::Frame SlipDataProcessor::parseFrame(const QByteArray &data) { Frame frame; QDataStream stream(data); stream >> frame.socketAddress; while (!stream.atEnd()) { quint8 dataByte; stream >> dataByte; frame.data.append(dataByte); } return frame; } QByteArray SlipDataProcessor::buildFrame(const Frame &frame) { QByteArray data; #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) QDataStream stream(&data, QDataStream::WriteOnly); #else QDataStream stream(&data, QIODevice::WriteOnly); #endif stream << frame.socketAddress; for (int i = 0; i < frame.data.size(); i++) { stream << static_cast(frame.data.at(i)); } return data; }