Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QDtls Client questions



  • Hallo,
    I wanted to ask, why exactly my client is behaving weirdly?

    QDtlsClient.hpp
    #pragma once

    #include <QObject>
    #include<QDtls>
    #include<qudpsocket.h>
    #include<qsslconfiguration.h>
    #include<qfile.h>
    #include<qsslkey.h>
    #include"enumerations.hpp"
    #include"VDtlsSocket.hpp"
    #include<future>
    
    class QDtlsClient : public QObject
    {
    	Q_OBJECT
    
    public:
    	QDtlsClient(SslInformation ssl, QObject* parent);
    	~QDtlsClient();
    
    	int64_t sendDatagram(const std::string& message, const QHostAddress& address, uint16_t port, const std::string& cookie = "");
    
    signals:
    	void errorMessage(const QString& message);
    	void warningMessage(const QString& message);
    	void infoMessage(const QString& message);
    	void serverResponse(const QHostAddress& addr,uint16_t port, const QString& plainText, const std::string& cookie);
    
    private slots:
    	void udpSocketConnected();
    	
    	void handshakeTimeout();
    	void pskRequired(QSslPreSharedKeyAuthenticator* auth);
    	void pingTimeout();
    	void messageReceived(VDtlsSocket* sender, const QString& message, const std::string& cookie);
    	
    
    private:
    	std::string addNewConnection(const QHostAddress& addr, uint16_t port, std::promise<bool>& prom);
    	std::optional<std::string> addNewConnection(const QHostAddress& addr, uint16_t port, const std::string& cookie, std::promise<bool>& prom);
    
    	QMap<std::string, VDtlsSocket*> socket;
    	QSslConfiguration clientConfiguration;
    	QString name;
    };
    

    QDtlsClient.cpp

    #include "QDtlsClient.hpp"
    
    QDtlsClient::QDtlsClient(SslInformation ssl,QObject *parent)
    	: QObject(parent)
    {
    	this->clientConfiguration = QSslConfiguration::defaultDtlsConfiguration();
    	QList<QSslCertificate> cas;
    	for (auto& cert : ssl.ca) {
    		QFile file(QString::fromStdString(cert));
    		file.open(QIODevice::ReadOnly);
    		cas.append(QSslCertificate(file.readAll()));
    		file.close();
    	}
    	this->clientConfiguration.setCaCertificates(cas);
    	QFile cert(QString::fromStdString(ssl.cert));
    	cert.open(QIODevice::ReadOnly);
    	this->clientConfiguration.setLocalCertificate(QSslCertificate(cert.readAll()));
    	QFile key(QString::fromStdString(ssl.key));
    	key.open(QIODevice::ReadOnly);
    	this->clientConfiguration.setPrivateKey(QSslKey(key.readAll(), QSsl::KeyAlgorithm::Rsa));
    	this->clientConfiguration.setPeerVerifyMode(QSslSocket::PeerVerifyMode::VerifyNone);
    }
    
    QDtlsClient::~QDtlsClient()
    {
    }
    
    int64_t QDtlsClient::sendDatagram(const std::string& message, const QHostAddress& address, uint16_t port, const std::string& cookie)
    {
    	std::string nCookie;
    	std::promise<bool> prom;
    	auto handshakeOver = prom.get_future();
    	if (cookie.empty()) {
    		nCookie = this->addNewConnection(address, port,prom);
    	}
    	else
    		nCookie = cookie;
    	auto pair = this->socket.find(nCookie);
    	if (pair == this->socket.end()) {
    		this->addNewConnection(address, port, cookie,prom);
    		pair = this->socket.find(nCookie);
    		if (pair == this->socket.end()) {
    			emit this->errorMessage("Could not find connection");
    			return -1;
    		}
    	}
    	handshakeOver.wait();
    	if (handshakeOver.get() == false) {
    		emit this->errorMessage("Handshake failed");
    		return -1;
    	}
    	auto sock = pair.value();
    	//sock->writeDtlsDatagram("Hallo Welt");
    	//std::this_thread::sleep_for(std::chrono::milliseconds(5000));
    	return sock->writeDtlsDatagram(QByteArray(message.c_str()));
    	//return int64_t();
    }
    
    void QDtlsClient::udpSocketConnected() {
    
    }
    
    void QDtlsClient::handshakeTimeout()
    {
    }
    
    void QDtlsClient::pskRequired(QSslPreSharedKeyAuthenticator* auth)
    {
    }
    
    void QDtlsClient::pingTimeout()
    {
    }
    
    void QDtlsClient::messageReceived(VDtlsSocket* sender, const QString& message, const std::string& cookie)
    {
    	emit this->serverResponse(sender->peerAddress(), sender->peerPort(), message, cookie);
    }
    
    std::string QDtlsClient::addNewConnection(const QHostAddress& addr, uint16_t port,std::promise<bool>& prom) {
    	VDtlsSocket* dtls = new VDtlsSocket(this->clientConfiguration);
    	std::string cookie = ::randomString();
    	connect(dtls, &VDtlsSocket::messageReceive, this, &QDtlsClient::messageReceived);
    	
    	dtls->connectToHost(addr, port,prom);
    	this->socket.insert(cookie, dtls);
    	return cookie;
    }
    
    std::optional<std::string> QDtlsClient::addNewConnection(const QHostAddress& addr, uint16_t port, const std::string& cookie,std::promise<bool>& prom)
    {
    	VDtlsSocket* dtls = new VDtlsSocket(this->clientConfiguration);
    	connect(dtls, &VDtlsSocket::messageReceive, this, &QDtlsClient::messageReceived);
    	dtls->connectToHost(addr, port,prom);
    	this->socket.insert(cookie, dtls);
    	return std::optional<std::string>(cookie);
    }
    

    VDtlsSocket.hpp

    #pragma once
    
    #include <QObject.h>
    #include<qudpsocket.h>
    #include<qsslconfiguration.h>
    #include<qdtls.h>
    #include<future>
    #include<qsslpresharedkeyauthenticator.h>
    
    class VDtlsSocket : public QUdpSocket
    {
    	Q_OBJECT
    
    public:
    	VDtlsSocket(const QSslConfiguration& config, QSslSocket::SslMode mode = QSslSocket::SslMode::SslClientMode, const std::string& cookie = "",QObject *parent = nullptr);
    	~VDtlsSocket();
    
    	operator QDtls* ();
    	operator QDtls& ();
    	operator const QDtls& () const;
    
    	//operator QUdpSocket* ();
    	//operator QUdpSocket& ();
    	//operator const QUdpSocket& () const;
    
    	virtual void connectToHost(const QHostAddress& addr, quint16 port, std::promise<bool>& prom, QIODevice::OpenMode openMode = QIODevice::ReadWrite);
    	virtual int64_t writeDtlsDatagram(const QByteArray& data);
    	void pskRequired(QSslPreSharedKeyAuthenticator* auth);
    	bool handshakeError() const;
    
    signals:
    	void messageReceive(VDtlsSocket* sender, const QString& message, const std::string& cookie);
    	void errorMessage(const QString& message);
    	void infoMessage(const QString& message);
    	void handshakeSuccessful();
    
    	private slots:
    		void mReadyRead();
    
    private:
    	QDtls crypto;
    	const std::string cookie;
    	bool mHandshakeError = false;
    };
    

    VDtlsSocket.cpp

    #include "VDtlsSocket.hpp"
    Q_DECLARE_METATYPE(std::string)
    auto id_string = qRegisterMetaType<std::string>("std::string");
    
    VDtlsSocket::VDtlsSocket(const QSslConfiguration& config, QSslSocket::SslMode mode, const std::string& cookie, QObject *parent)
    	: crypto(mode),QUdpSocket(parent), cookie(cookie)
    {
    	this->crypto.setDtlsConfiguration(config);
    	connect(this, &QAbstractSocket::readyRead, this, &VDtlsSocket::mReadyRead);
    	connect(&this->crypto, &QDtls::pskRequired, this, &VDtlsSocket::pskRequired);
    }
    
    VDtlsSocket::~VDtlsSocket()
    {
    }
    
    VDtlsSocket::operator QDtls* ()
    {
    	return &this->crypto;
    }
    
    VDtlsSocket::operator QDtls& ()
    {
    	return this->crypto;
    }
    
    VDtlsSocket::operator const QDtls& () const
    {
    	return this->crypto;
    }
    
    void VDtlsSocket::connectToHost(const QHostAddress& addr, quint16 port, std::promise<bool>& prom, QIODevice::OpenMode openMode)
    {
    	QUdpSocket::connectToHost(addr, port, openMode);
    	this->crypto.setPeer(addr, port);
    	if (!this->crypto.doHandshake(this)) {
    		emit this->errorMessage("could not commit handshake");
    		this->close();
    		prom.set_value(false);
    		return;
    	}
    	emit this->handshakeSuccessful();
    	prom.set_value(true);
    }
    
    int64_t VDtlsSocket::writeDtlsDatagram(const QByteArray& data)
    {
    	return this->crypto.writeDatagramEncrypted(this,data);
    }
    
    void VDtlsSocket::pskRequired(QSslPreSharedKeyAuthenticator* auth)
    {
    	auth->setIdentity("TEST");
    	auth->setPreSharedKey(QByteArrayLiteral("\x1a\x2b\x3c\x4d\x5e\x6f"));
    }
    
    bool VDtlsSocket::handshakeError() const
    {
    	return this->mHandshakeError;
    }
    
    void VDtlsSocket::mReadyRead() {
    	QDtls& p = *this;
    	QByteArray dgram(this->pendingDatagramSize(), Qt::Uninitialized);
    	uint64_t bytesRead = this->readDatagram(dgram.data(), dgram.size());
    	if (bytesRead < 1) {
    		emit errorMessage("Could not read Datagram");
    		this->mHandshakeError = true;
    		return;
    	}
    	dgram.resize(bytesRead);
    	if (p.isConnectionEncrypted()) {
    		const QByteArray arr = p.decryptDatagram(this, dgram);
    		emit this->messageReceive(this, arr,this->cookie);
    		return;
    	}
    	else {
    		if (!p.doHandshake(this, dgram)) {
    			emit this->errorMessage("failed Handshake "+p.dtlsErrorString());
    			return;
    		}
    	}
    }
    

    The Function who starts the Client

    void KSecureDesktopQT::startChat(QListWidgetItem* item)
    {
        auto* i = static_cast<VListWidgetItem*>(item);
        auto data = i->getData<UserInformation>();
        std::string ranstr = "";
        if (data.username == std::string("TestUser")) {
            ranstr = "abc";
        }
        else {
            ranstr = randomString();
            //data.cookie = (ranstr);
        }
    
        if (data.ip.empty()) {
    
        }
        ranstr = "abc";
        auto len = this->client->sendDatagram("HALLO", QHostAddress(QString::fromStdString(data.ip)), data.port, ranstr);
        //len = this->client->sendDatagram("HALLO", QHostAddress(QString::fromStdString(data.ip)), data.port, ranstr);
        /*
        auto iter = this->chats.insert(QString::fromStdString(ranstr), new KChatDialog([&](const std::vector<UserInformation>& to, const std::string& data) 
            {this->sendChatCallback(to, data); }, [&](const std::vector<UserInformation>& to, const std::u16string& path) { this->sendChatFileCallback(to, path); }, 
            [&](const std::string& from, const std::u16string& path, const std::optional<std::u16string>& target) { this->fileReplyChatFunction(from, path, target); }, 
            { data }, ranstr,
            this->language));
        iter.value()->setAttribute(Qt::WA_DeleteOnClose);
        iter.value()->show();
        connect(iter.value(), &KChatDialog::emitExit, this, &KSecureDesktopQT::windowClosed);*/
    }
    

    The Problem is that after end of StartChat Funtion Wireshark is saying it is still at Hello Verify Request after it jumps out of the function it says it continues establishing the session.
    It ends with New Session Ticket, Change Cipher Spec, Encrypted Handshake Message from Server.
    if I try to restart the function it gets stuck


Log in to reply