mirror of
https://github.com/itay-grudev/SingleApplication.git
synced 2025-01-15 17:02:06 +08:00
Fix sendmessage (#46)
* Fix send message example If a secondary instance sends a message immediately after connecting, the message follows the init message. This causes the slotConnectionEstablished to read and consume the tail of the message and interpret it as the checksum. The checksum fails and the connection becomes invalid. To avoid this race, we prefix the init message with its length. This way, we consume only the data relevant to the init message. This patch fixes the sending_arguments example. Signed-off-by: Francis Giraldeau <francis.giraldeau@gmail.com> * Fix include file case Signed-off-by: Francis Giraldeau <francis.giraldeau@nrc-cnrc.gc.ca>
This commit is contained in:
parent
a36a327ddf
commit
f975da90cc
@ -1,4 +1,4 @@
|
|||||||
#include <SingleApplication.h>
|
#include <singleapplication.h>
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
@ -50,7 +50,7 @@
|
|||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
|
||||||
#include <SingleApplication.h>
|
#include <singleapplication.h>
|
||||||
|
|
||||||
#include "calculator.h"
|
#include "calculator.h"
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#include <SingleApplication.h>
|
#include <singleapplication.h>
|
||||||
#include "messagereceiver.h"
|
#include "messagereceiver.h"
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
|
@ -216,6 +216,13 @@ void SingleApplicationPrivate::connectToPrimary( int msecs, ConnectionType conne
|
|||||||
quint16 checksum = qChecksum(initMsg.constData(), static_cast<quint32>(initMsg.length()));
|
quint16 checksum = qChecksum(initMsg.constData(), static_cast<quint32>(initMsg.length()));
|
||||||
writeStream << checksum;
|
writeStream << checksum;
|
||||||
|
|
||||||
|
// The header indicates the message length that follows
|
||||||
|
QByteArray header;
|
||||||
|
QDataStream headerStream(&header, QIODevice::WriteOnly);
|
||||||
|
headerStream.setVersion(QDataStream::Qt_5_6);
|
||||||
|
headerStream << (quint64) initMsg.length();
|
||||||
|
|
||||||
|
socket->write( header );
|
||||||
socket->write( initMsg );
|
socket->write( initMsg );
|
||||||
socket->flush();
|
socket->flush();
|
||||||
socket->waitForBytesWritten( msecs );
|
socket->waitForBytesWritten( msecs );
|
||||||
@ -274,33 +281,43 @@ void SingleApplicationPrivate::slotConnectionEstablished()
|
|||||||
quint32 instanceId = 0;
|
quint32 instanceId = 0;
|
||||||
ConnectionType connectionType = InvalidConnection;
|
ConnectionType connectionType = InvalidConnection;
|
||||||
if( nextConnSocket->waitForReadyRead( 100 ) ) {
|
if( nextConnSocket->waitForReadyRead( 100 ) ) {
|
||||||
// read all data from message in same order/format as written
|
// read the fields in same order and format as written
|
||||||
QByteArray msgBytes = nextConnSocket->read(nextConnSocket->bytesAvailable() - static_cast<qint64>(sizeof(quint16)));
|
QDataStream headerStream(nextConnSocket);
|
||||||
QByteArray checksumBytes = nextConnSocket->read(sizeof(quint16));
|
headerStream.setVersion(QDataStream::Qt_5_6);
|
||||||
|
|
||||||
|
// Read the header to know the message length
|
||||||
|
quint64 msgLen = 0;
|
||||||
|
headerStream >> msgLen;
|
||||||
|
|
||||||
|
if (msgLen >= sizeof(quint16)) {
|
||||||
|
// Read the message body
|
||||||
|
QByteArray msgBytes = nextConnSocket->read(msgLen);
|
||||||
QDataStream readStream(msgBytes);
|
QDataStream readStream(msgBytes);
|
||||||
readStream.setVersion(QDataStream::Qt_5_6);
|
readStream.setVersion(QDataStream::Qt_5_6);
|
||||||
|
|
||||||
// server name
|
// server name
|
||||||
QByteArray latin1Name;
|
QByteArray latin1Name;
|
||||||
readStream >> latin1Name;
|
readStream >> latin1Name;
|
||||||
// connectioon type
|
|
||||||
|
// connection type
|
||||||
quint8 connType = InvalidConnection;
|
quint8 connType = InvalidConnection;
|
||||||
readStream >> connType;
|
readStream >> connType;
|
||||||
connectionType = static_cast<ConnectionType>(connType);
|
connectionType = static_cast<ConnectionType>(connType);
|
||||||
|
|
||||||
// instance id
|
// instance id
|
||||||
readStream >> instanceId;
|
readStream >> instanceId;
|
||||||
|
|
||||||
// checksum
|
// checksum
|
||||||
quint16 msgChecksum = 0;
|
quint16 msgChecksum = 0;
|
||||||
QDataStream checksumStream(checksumBytes);
|
readStream >> msgChecksum;
|
||||||
checksumStream.setVersion(QDataStream::Qt_5_6);
|
|
||||||
checksumStream >> msgChecksum;
|
|
||||||
|
|
||||||
const quint16 actualChecksum = qChecksum(msgBytes.constData(), static_cast<quint32>(msgBytes.length()));
|
const quint16 actualChecksum = qChecksum(msgBytes.constData(), static_cast<quint32>(msgBytes.length() - sizeof(quint16)));
|
||||||
|
|
||||||
if (readStream.status() != QDataStream::Ok || QLatin1String(latin1Name) != blockServerName || msgChecksum != actualChecksum) {
|
if (readStream.status() != QDataStream::Ok || QLatin1String(latin1Name) != blockServerName || msgChecksum != actualChecksum) {
|
||||||
connectionType = InvalidConnection;
|
connectionType = InvalidConnection;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if( connectionType == InvalidConnection ) {
|
if( connectionType == InvalidConnection ) {
|
||||||
nextConnSocket->close();
|
nextConnSocket->close();
|
||||||
|
Loading…
Reference in New Issue
Block a user