Browse Source

Fix access violation

pull/45/head 0.6.8
adityapk00 5 years ago
parent
commit
48bef601de
  1. 34
      src/websockets.cpp
  2. 27
      src/websockets.h

34
src/websockets.cpp

@ -5,6 +5,19 @@
#include "ui_mobileappconnector.h" #include "ui_mobileappconnector.h"
#include "version.h" #include "version.h"
// Weap the sendTextMessage to check if the connection is valid and that the parent WebServer didn't close this connection
// for some reason.
void ClientWebSocket::sendTextMessage(QString m) {
if (client) {
if (server && !server->isValidConnection(client)) {
return;
}
if (client->isValid())
client->sendTextMessage(m);
}
}
WSServer::WSServer(quint16 port, bool debug, QObject *parent) : WSServer::WSServer(quint16 port, bool debug, QObject *parent) :
QObject(parent), QObject(parent),
m_pWebSocketServer(new QWebSocketServer(QStringLiteral("Direct Connection Server"), m_pWebSocketServer(new QWebSocketServer(QStringLiteral("Direct Connection Server"),
@ -46,7 +59,8 @@ void WSServer::processTextMessage(QString message)
qDebug() << "Message received:" << message; qDebug() << "Message received:" << message;
if (pClient) { if (pClient) {
AppDataServer::getInstance()->processMessage(message, m_mainWindow, pClient, AppConnectionType::DIRECT); std::shared_ptr<ClientWebSocket> client = std::make_shared<ClientWebSocket>(pClient, this);
AppDataServer::getInstance()->processMessage(message, m_mainWindow, client, AppConnectionType::DIRECT);
} }
} }
@ -153,7 +167,7 @@ void WormholeClient::onConnected()
void WormholeClient::onTextMessageReceived(QString message) void WormholeClient::onTextMessageReceived(QString message)
{ {
AppDataServer::getInstance()->processMessage(message, parent, m_webSocket, AppConnectionType::INTERNET); AppDataServer::getInstance()->processMessage(message, parent, std::make_shared<ClientWebSocket>(m_webSocket), AppConnectionType::INTERNET);
} }
@ -508,7 +522,7 @@ QString AppDataServer::decryptMessage(QJsonDocument msg, QString secretHex, QStr
} }
// Process an incoming text message. The message has to be encrypted with the secret key (or the temporary secret key) // Process an incoming text message. The message has to be encrypted with the secret key (or the temporary secret key)
void AppDataServer::processMessage(QString message, MainWindow* mainWindow, QWebSocket* pClient, AppConnectionType connType) { void AppDataServer::processMessage(QString message, MainWindow* mainWindow, std::shared_ptr<ClientWebSocket> pClient, AppConnectionType connType) {
auto replyWithError = [=]() { auto replyWithError = [=]() {
auto r = QJsonDocument(QJsonObject{ auto r = QJsonDocument(QJsonObject{
{"error", "Encryption error"}, {"error", "Encryption error"},
@ -591,7 +605,7 @@ void AppDataServer::processMessage(QString message, MainWindow* mainWindow, QWeb
} }
// Decrypted method will be executed here. // Decrypted method will be executed here.
void AppDataServer::processDecryptedMessage(QString message, MainWindow* mainWindow, QWebSocket* pClient) { void AppDataServer::processDecryptedMessage(QString message, MainWindow* mainWindow, std::shared_ptr<ClientWebSocket> pClient) {
// First, extract the command from the message // First, extract the command from the message
auto msg = QJsonDocument::fromJson(message.toUtf8()); auto msg = QJsonDocument::fromJson(message.toUtf8());
@ -623,7 +637,7 @@ void AppDataServer::processDecryptedMessage(QString message, MainWindow* mainWin
} }
// "sendTx" command. This method will actually send money, so be careful with everything // "sendTx" command. This method will actually send money, so be careful with everything
void AppDataServer::processSendTx(QJsonObject sendTx, MainWindow* mainwindow, QWebSocket* pClient) { void AppDataServer::processSendTx(QJsonObject sendTx, MainWindow* mainwindow, std::shared_ptr<ClientWebSocket> pClient) {
auto error = [=](QString reason) { auto error = [=](QString reason) {
auto r = QJsonDocument(QJsonObject{ auto r = QJsonDocument(QJsonObject{
{"errorCode", -1}, {"errorCode", -1},
@ -693,8 +707,7 @@ void AppDataServer::processSendTx(QJsonObject sendTx, MainWindow* mainwindow, QW
{"command", "sendTxSubmitted"}, {"command", "sendTxSubmitted"},
{"txid", txid} {"txid", txid}
}).toJson(); }).toJson();
if (pClient->isValid()) pClient->sendTextMessage(encryptOutgoing(r));
pClient->sendTextMessage(encryptOutgoing(r));
}, },
// Errored while submitting Tx // Errored while submitting Tx
[=] (QString, QString errStr) { [=] (QString, QString errStr) {
@ -703,8 +716,7 @@ void AppDataServer::processSendTx(QJsonObject sendTx, MainWindow* mainwindow, QW
{"command", "sendTxFailed"}, {"command", "sendTxFailed"},
{"err", errStr} {"err", errStr}
}).toJson(); }).toJson();
if (pClient->isValid()) pClient->sendTextMessage(encryptOutgoing(r));
pClient->sendTextMessage(encryptOutgoing(r));
} }
); );
@ -717,7 +729,7 @@ void AppDataServer::processSendTx(QJsonObject sendTx, MainWindow* mainwindow, QW
} }
// "getInfo" command // "getInfo" command
void AppDataServer::processGetInfo(QJsonObject jobj, MainWindow* mainWindow, QWebSocket* pClient) { void AppDataServer::processGetInfo(QJsonObject jobj, MainWindow* mainWindow, std::shared_ptr<ClientWebSocket> pClient) {
auto connectedName = jobj["name"].toString(); auto connectedName = jobj["name"].toString();
if (mainWindow == nullptr || mainWindow->getRPC() == nullptr || if (mainWindow == nullptr || mainWindow->getRPC() == nullptr ||
@ -758,7 +770,7 @@ void AppDataServer::processGetInfo(QJsonObject jobj, MainWindow* mainWindow, QWe
pClient->sendTextMessage(encryptOutgoing(r)); pClient->sendTextMessage(encryptOutgoing(r));
} }
void AppDataServer::processGetTransactions(MainWindow* mainWindow, QWebSocket* pClient) { void AppDataServer::processGetTransactions(MainWindow* mainWindow, std::shared_ptr<ClientWebSocket> pClient) {
QJsonArray txns; QJsonArray txns;
auto model = mainWindow->getRPC()->getTransactionsModel(); auto model = mainWindow->getRPC()->getTransactionsModel();

27
src/websockets.h

@ -10,11 +10,28 @@
QT_FORWARD_DECLARE_CLASS(QWebSocketServer) QT_FORWARD_DECLARE_CLASS(QWebSocketServer)
QT_FORWARD_DECLARE_CLASS(QWebSocket) QT_FORWARD_DECLARE_CLASS(QWebSocket)
class WSServer;
// We're going to wrap the websocket in this class, because the underlying QWebSocket might get closed
// or deleted while a callback is waiting to get the data back. Therefore, we write a custom "sendTextMessage"
// class that checks all this before sending.
class ClientWebSocket {
public:
ClientWebSocket(QWebSocket* c, WSServer* s = nullptr) { client = c; server = s; }
void sendTextMessage(QString m);
void close(QWebSocketProtocol::CloseCode code, const QString& msg) { client->close(code, msg); }
private:
QWebSocket* client;
WSServer* server;
};
class WSServer : public QObject class WSServer : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit WSServer(quint16 port, bool debug = false, QObject *parent = nullptr); explicit WSServer(quint16 port, bool debug = false, QObject *parent = nullptr);
bool isValidConnection(QWebSocket* c) { return m_clients.contains(c); }
~WSServer(); ~WSServer();
Q_SIGNALS: Q_SIGNALS:
@ -82,11 +99,11 @@ public:
void updateConnectedUI(); void updateConnectedUI();
void updateUIWithNewQRCode(MainWindow* mainwindow); void updateUIWithNewQRCode(MainWindow* mainwindow);
void processSendTx(QJsonObject sendTx, MainWindow* mainwindow, QWebSocket* pClient); void processSendTx(QJsonObject sendTx, MainWindow* mainwindow, std::shared_ptr<ClientWebSocket> pClient);
void processMessage(QString message, MainWindow* mainWindow, QWebSocket* pClient, AppConnectionType connType); void processMessage(QString message, MainWindow* mainWindow, std::shared_ptr<ClientWebSocket> pClient, AppConnectionType connType);
void processGetInfo(QJsonObject jobj, MainWindow* mainWindow, QWebSocket* pClient); void processGetInfo(QJsonObject jobj, MainWindow* mainWindow, std::shared_ptr<ClientWebSocket> pClient);
void processDecryptedMessage(QString message, MainWindow* mainWindow, QWebSocket* pClient); void processDecryptedMessage(QString message, MainWindow* mainWindow, std::shared_ptr<ClientWebSocket> pClient);
void processGetTransactions(MainWindow* mainWindow, QWebSocket* pClient); void processGetTransactions(MainWindow* mainWindow, std::shared_ptr<ClientWebSocket> pClient);
QString decryptMessage(QJsonDocument msg, QString secretHex, QString lastRemoteNonceHex); QString decryptMessage(QJsonDocument msg, QString secretHex, QString lastRemoteNonceHex);
QString encryptOutgoing(QString msg); QString encryptOutgoing(QString msg);

Loading…
Cancel
Save