Skip to content

Commit

Permalink
Fix sendmessage (#46)
Browse files Browse the repository at this point in the history
* 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>
  • Loading branch information
giraldeau authored and itay-grudev committed Jul 26, 2018
1 parent a36a327 commit f975da9
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 28 deletions.
2 changes: 1 addition & 1 deletion examples/basic/main.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include <SingleApplication.h>
#include <singleapplication.h>

int main(int argc, char *argv[])
{
Expand Down
2 changes: 1 addition & 1 deletion examples/calculator/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@

#include <QApplication>

#include <SingleApplication.h>
#include <singleapplication.h>

#include "calculator.h"

Expand Down
2 changes: 1 addition & 1 deletion examples/sending_arguments/main.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include <SingleApplication.h>
#include <singleapplication.h>
#include "messagereceiver.h"

int main(int argc, char *argv[])
Expand Down
67 changes: 42 additions & 25 deletions singleapplication.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,13 @@ void SingleApplicationPrivate::connectToPrimary( int msecs, ConnectionType conne
quint16 checksum = qChecksum(initMsg.constData(), static_cast<quint32>(initMsg.length()));
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->flush();
socket->waitForBytesWritten( msecs );
Expand Down Expand Up @@ -274,31 +281,41 @@ void SingleApplicationPrivate::slotConnectionEstablished()
quint32 instanceId = 0;
ConnectionType connectionType = InvalidConnection;
if( nextConnSocket->waitForReadyRead( 100 ) ) {
// read all data from message in same order/format as written
QByteArray msgBytes = nextConnSocket->read(nextConnSocket->bytesAvailable() - static_cast<qint64>(sizeof(quint16)));
QByteArray checksumBytes = nextConnSocket->read(sizeof(quint16));
QDataStream readStream(msgBytes);
readStream.setVersion(QDataStream::Qt_5_6);

// server name
QByteArray latin1Name;
readStream >> latin1Name;
// connectioon type
quint8 connType = InvalidConnection;
readStream >> connType;
connectionType = static_cast<ConnectionType>(connType);
// instance id
readStream >> instanceId;
// checksum
quint16 msgChecksum = 0;
QDataStream checksumStream(checksumBytes);
checksumStream.setVersion(QDataStream::Qt_5_6);
checksumStream >> msgChecksum;

const quint16 actualChecksum = qChecksum(msgBytes.constData(), static_cast<quint32>(msgBytes.length()));

if (readStream.status() != QDataStream::Ok || QLatin1String(latin1Name) != blockServerName || msgChecksum != actualChecksum) {
connectionType = InvalidConnection;
// read the fields in same order and format as written
QDataStream headerStream(nextConnSocket);
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);
readStream.setVersion(QDataStream::Qt_5_6);

// server name
QByteArray latin1Name;
readStream >> latin1Name;

// connection type
quint8 connType = InvalidConnection;
readStream >> connType;
connectionType = static_cast<ConnectionType>(connType);

// instance id
readStream >> instanceId;

// checksum
quint16 msgChecksum = 0;
readStream >> msgChecksum;

const quint16 actualChecksum = qChecksum(msgBytes.constData(), static_cast<quint32>(msgBytes.length() - sizeof(quint16)));

if (readStream.status() != QDataStream::Ok || QLatin1String(latin1Name) != blockServerName || msgChecksum != actualChecksum) {
connectionType = InvalidConnection;
}
}
}

Expand Down

0 comments on commit f975da9

Please sign in to comment.