Merge PR #531: Some fixes in Coap

This commit is contained in:
jenkins 2022-06-30 15:04:35 +02:00
commit 48d5a182c6
4 changed files with 89 additions and 55 deletions

View File

@ -801,16 +801,15 @@ void Coap::hostLookupFinished(const QHostInfo &hostInfo)
void Coap::onReadyRead()
{
QHostAddress hostAddress;
QByteArray data;
quint16 port;
while (m_socket->hasPendingDatagrams()) {
data.resize(m_socket->pendingDatagramSize());
m_socket->readDatagram(data.data(), data.size(), &hostAddress, &port);
QByteArray datagram(m_socket->pendingDatagramSize(), 0);
m_socket->readDatagram(datagram.data(), datagram.size(), &hostAddress, &port);
qCDebug(dcCoap()) << "Datagram received from:" << hostAddress << ":" << datagram;
CoapPdu pdu(datagram);
processResponse(pdu, hostAddress, port);
}
CoapPdu pdu(data);
processResponse(pdu, hostAddress, port);
}
void Coap::onReplyTimeout()

View File

@ -163,6 +163,10 @@
#include <QMetaEnum>
#include <QTime>
#include <QLoggingCategory>
#include <QDataStream>
Q_DECLARE_LOGGING_CATEGORY(dcCoap)
/*! Constructs a CoapPdu with the given \a parent. */
CoapPdu::CoapPdu(QObject *parent) :
@ -370,7 +374,7 @@ void CoapPdu::addOption(const CoapOption::Option &option, const QByteArray &data
CoapOption o;
o.setOption(option);
o.setData(data);
m_options.insert(index + 1, o);
m_options.insert(qMin(m_options.length(), index + 1), o);
}
/*! Returns the block of this \l{CoapPdu}. */
@ -504,70 +508,97 @@ QByteArray CoapPdu::pack() const
void CoapPdu::unpack(const QByteArray &data)
{
// create a CoapPDU
if (data.length() < 4) {
m_error = InvalidPduSizeError;
}
quint8 *rawData = (quint8 *)data.data();
setVersion((rawData[0] & 0xc0) >> 6);
setMessageType(static_cast<MessageType>((rawData[0] & 0x30) >> 4));
quint8 tokenLength = (rawData[0] & 0xf);
QDataStream stream(data);
quint8 flags;
stream >> flags;
setVersion((flags & 0xc0) >> 6);
// qCDebug(dcCoap()) << "Version:" << m_version;
setMessageType(static_cast<MessageType>((flags & 0x30) >> 4));
// qCDebug(dcCoap()) << "Message Type:" << messageType();
quint8 tokenLength = flags & 0x0f;
// qCDebug(dcCoap()) << "Token length:" << tokenLength;
if (tokenLength > 8) {
qCWarning(dcCoap()) << "Inavalid token length" << tokenLength;
m_error = InvalidTokenError;
return;
}
setToken(QByteArray((const char *)rawData + 4, tokenLength));
setStatusCode(static_cast<StatusCode>(rawData[1]));
setMessageId((qint16)data.mid(2,2).toHex().toUInt(0,16));
quint8 reqRspCode;
stream >> reqRspCode;
setStatusCode(static_cast<StatusCode>(reqRspCode));
// qCDebug(dcCoap()) << "Req/Rsp code:" << statusCode();
// parse options
int index = 4 + tokenLength;
quint8 optionByte = rawData[index];
quint16 delta = 0;
while (QByteArray::number(optionByte, 16) != "ff" && optionByte != 0) {
quint16 optionNumber = ((optionByte & 0xf0) >> 4);
quint16 messageId;
stream >> messageId;
setMessageId(messageId);
// qCDebug(dcCoap()) << "Message ID:" << messageId;
char tokenData[tokenLength];
if (stream.readRawData(tokenData, tokenLength) != tokenLength) {
qCWarning(dcCoap()) << "Token data not complete.";
m_error = InvalidTokenError;
return;
}
QByteArray token(tokenData, tokenLength);
setToken(token);
// qCDebug(dcCoap()) << "Token:" << token.toHex();
// check option delta
if (optionNumber < 13) {
delta += optionNumber;
} else if (optionNumber == 13) {
// extended 8 bit option delta
delta += (quint8)(rawData[index + 1] + 13);
index += 1;
} else if (optionNumber == 14) {
// extended 16 bit option delta
delta += ((rawData[index + 1] << 8) | rawData[index + 2]) + 269;
index += 2;
} else if (optionNumber == 15) {
m_error = InvalidOptionDeltaError;
while (!stream.atEnd()) {
quint8 optionByte;
stream >> optionByte;
// qCDebug(dcCoap()) << "OptionByte:" << optionByte;
if (optionByte == 0xff) {
char payloadData[65507]; // Max UDP datagram size
int payloadLength = stream.readRawData(payloadData, 65507);
if (payloadLength > 0) {
setPayload(QByteArray(payloadData, payloadLength));
}
return;
}
quint16 optionDelta;
optionDelta = (optionByte & 0xf0) >> 4;
// qCDebug(dcCoap()) << "Option delta:" << optionDelta;
quint16 optionLength = (optionByte & 0x0f);
// qCDebug(dcCoap()) << "Option length:" << optionLength;
if (optionDelta == 13) {
quint8 optionDeltaExtended;
stream >> optionDeltaExtended;
optionDelta = optionDeltaExtended + 13;
// qCDebug(dcCoap()).nospace() << "Extended option delta (8 bit): " << optionDelta << " (" << optionDeltaExtended << " + 13)";
} else if (optionDelta == 14) {
quint16 optionDeltaExtended;
stream >> optionDeltaExtended;
optionDelta = optionDeltaExtended + 269;
// qCDebug(dcCoap()).nospace() << "Extended option delta (16 bit): " << optionDelta << " (" << optionDeltaExtended << " + 269)";
}
// check option length
quint16 optionLength = (optionByte & 0xf);
if (optionLength == 13) {
// extended 8 bit option length
optionLength = (quint8)(rawData[index + 1] - 13);
index += 1;
quint8 optionLengthExtended;
stream >> optionLengthExtended;
optionLength = optionLengthExtended + 13;
// qCDebug(dcCoap()).nospace() << "Extended option length (8 bit): " << optionLength << " (" << optionLengthExtended << " + 13)";
} else if (optionLength == 14) {
// extended 16 bit option delta
optionLength = ((rawData[index + 1] << 8) | rawData[index + 2]) - 269;
index += 2;
} else if (optionLength == 15) {
m_error = InvalidOptionLengthError;
quint16 optionLengthExtended;
stream >> optionLengthExtended;
optionLength = optionLengthExtended + 269;
// qCDebug(dcCoap()).nospace() << "Extended option kength (16 bit): " << optionDelta << " (" << optionLengthExtended << " + 269)";
}
QByteArray optionData = QByteArray((const char *)rawData + index + 1, optionLength);
addOption(static_cast<CoapOption::Option>(delta), optionData);
char optionData[optionLength];
stream.readRawData(optionData, optionLength);
// qCDebug(dcCoap()) << "Option data:" << QByteArray(optionData, optionLength);
index += optionLength + 1;
optionByte = rawData[index];
if (QByteArray::number(optionByte, 16) == "ff") {
setPayload(data.right(data.length() - index - 1));
break;
}
addOption(static_cast<CoapOption::Option>(optionDelta), QByteArray(optionData, optionLength));
}
}

View File

@ -68,6 +68,7 @@ public:
Acknowledgement = 0x02,
Reset = 0x03
};
Q_ENUM(MessageType)
// Methods: https://tools.ietf.org/html/rfc7252#section-5.8
// Respond codes: https://tools.ietf.org/html/rfc7252#section-12.1.2
@ -101,6 +102,7 @@ public:
GatewayTimeout = 0xa4, // 5.04
ProxyingNotSupported = 0xa5 // 5.05
};
Q_ENUM(StatusCode)
// https://tools.ietf.org/html/rfc7252#section-12.3
enum ContentType {
@ -111,6 +113,7 @@ public:
ApplicationExi = 47,
ApplicationJson = 50
};
Q_ENUM(ContentType)
enum Error {
NoError,
@ -120,6 +123,7 @@ public:
InvalidOptionLengthError,
UnknownOptionError
};
Q_ENUM(Error)
CoapPdu(QObject *parent = 0);
CoapPdu(const QByteArray &data, QObject *parent = 0);

View File

@ -132,8 +132,8 @@ private:
int m_messageId;
QByteArray m_messageToken;
bool m_observation;
bool m_observationEnable;
bool m_observation = false;
bool m_observationEnable = false;
signals:
void timeout();