2024-04-29 Fred Gleason <fredg@paravelsystems.com>

* Fixed a race condition in the PAD XML feed that could cause corrupt
	updates.

Signed-off-by: Fred Gleason <fredg@paravelsystems.com>
This commit is contained in:
Fred Gleason
2024-04-29 17:20:50 -04:00
parent d26762493b
commit f8dfc52cf0
8 changed files with 231 additions and 138 deletions

View File

@@ -163,6 +163,7 @@ dist_librd_la_SOURCES = dbversion.h\
rdimport_audio.cpp rdimport_audio.h\
rdinstancelock.cpp rdinstancelock.h\
rdjackclientlistmodel.cpp rdjackclientlistmodel.h\
rdjsonframer.cpp rdjsonframer.h\
rdkernelgpio.cpp rdkernelgpio.h\
rdlibrary_conf.cpp rdlibrary_conf.h\
rdlibrarymodel.cpp rdlibrarymodel.h\
@@ -363,6 +364,7 @@ nodist_librd_la_SOURCES = moc_rdadd_cart.cpp\
moc_rdimagepickermodel.cpp\
moc_rdimport_audio.cpp\
moc_rdjackclientlistmodel.cpp\
moc_rdjsonframer.cpp\
moc_rdkernelgpio.cpp\
moc_rdlibrarymodel.cpp\
moc_rdlineedit.cpp\

View File

@@ -127,6 +127,7 @@ SOURCES += rdimagepickermodel.cpp
SOURCES += rdimport_audio.cpp
SOURCES += rdkernelgpio.cpp
SOURCES += rdjackclientlistmodel.cpp
SOURCES += rdjsonframer.cpp
SOURCES += rdlibrary_conf.cpp
SOURCES += rdlibrarymodel.cpp
SOURCES += rdlineedit.cpp
@@ -319,6 +320,7 @@ HEADERS += rdimagepickerbox.h
HEADERS += rdimagepickermodel.h
HEADERS += rdimport_audio.h
HEADERS += rdjackclientlistmodel.h
HEADERS += rdjsonframer.h
HEADERS += rdkernelgpio.h
HEADERS += rdlibrary_conf.h
HEADERS += rdlibrarymodel.h

115
lib/rdjsonframer.cpp Normal file
View File

@@ -0,0 +1,115 @@
// rdjsonframer.cpp
//
// Frame an unsynchronized stream of JSON messages
//
// (C) Copyright 2024 Fred Gleason <fredg@paravelsystems.com>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU Library General Public License
// version 2 as published by the Free Software Foundation.
//
// This program 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public
// License along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#include "rdjsonframer.h"
RDJsonFramer::RDJsonFramer(QTcpSocket *in_sock,QObject *parent)
: QObject(parent)
{
d_escaped=false;
d_quoted=false;
d_level=0;
d_socket=in_sock;
connect(d_socket,SIGNAL(readyRead()),this,SLOT(readyReadData()));
}
RDJsonFramer::RDJsonFramer(QObject *parent)
: QObject(parent)
{
d_escaped=false;
d_quoted=false;
d_level=0;
d_socket=NULL;
}
RDJsonFramer::~RDJsonFramer()
{
if(d_socket!=NULL) {
delete d_socket;
}
}
QByteArray RDJsonFramer::currentDocument() const
{
return d_current_document;
}
void RDJsonFramer::write(const QByteArray &data)
{
for(int i=0;i<data.size();i++) {
QChar c=data.at(i);
d_data+=c;
if((c.cell()=='\\')&&(!d_escaped)) {
d_escaped=true;
}
else {
switch(c.cell()) {
case '{':
if(!d_quoted) {
d_level++;
}
break;
case '}':
if(!d_quoted) {
if(--d_level==0) {
d_current_document=d_data+"\n";
d_escaped=false;
d_quoted=false;
d_level=0;
d_data.clear();
emit documentReceived(d_current_document);
}
}
break;
case '"':
if(!d_escaped) {
d_quoted=!d_quoted;
}
break;
}
d_escaped=false;
}
}
}
void RDJsonFramer::reset()
{
d_escaped=false;
d_quoted=false;
d_level=0;
d_data.clear();
emit documentReset();
}
void RDJsonFramer::readyReadData()
{
write(d_socket->readAll());
}

58
lib/rdjsonframer.h Normal file
View File

@@ -0,0 +1,58 @@
// rdjsonframer.h
//
// Frame an unsynchronized stream of JSON messages
//
// (C) Copyright 2024 Fred Gleason <fredg@paravelsystems.com>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU Library General Public License
// version 2 as published by the Free Software Foundation.
//
// This program 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public
// License along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#ifndef RDJSONFRAMER_H
#define RDJSONFRAMER_H
#include <QByteArray>
#include <QObject>
#include <QTcpSocket>
class RDJsonFramer : public QObject
{
Q_OBJECT
public:
RDJsonFramer(QTcpSocket *in_sock,QObject *parent);
RDJsonFramer(QObject *parent);
~RDJsonFramer();
QByteArray currentDocument() const;
public slots:
void write(const QByteArray &data);
void reset();
signals:
void documentReceived(const QByteArray &jdoc);
void documentReset();
private slots:
void readyReadData();
private:
QByteArray d_data;
bool d_escaped;
bool d_quoted;
int d_level;
QByteArray d_current_document;
QTcpSocket *d_socket;
};
#endif // RDJSONFRAMER_H