PDA

View Full Version : QSslSocket : Having troubles



Nyphel
22nd June 2007, 14:37
Hi !

I'm under Windows 2000 Pro, using the beautifull Qt4.3 open source version.
This has not been recompiled, and it is configured in shared/debug.
I've downloaed and installed the OpenSSL library, but I don't think this will help me.

I was using a QtcpSocket on Qt4.2.3 to connect an IMAP server.
Now I replaced it by a QSslSocket, that inherits from QtcpSocket, but I'm having troubles.



Myclass.h :


#include <QObject>
#include <QTcpSocket>
#include <QList>
#include <QString>
#include <QSslSocket>
#include <QProcess>

class MailChecker : public QObject
{
Q_OBJECT

public:
MailChecker();
void Check();

private slots:
void SLOT_socket_proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *);
void SLOT_socket_sslErrors(const QList<QSslError>);
void SLOT_socket_stateChanged(QAbstractSocket::SocketSt ate);
void SLOT_socket_connected();
void SLOT_socket_disconnected();
void SLOT_socket_encrypted();
void SLOT_socket_hostFound();

private:
QSslSocket *sockect_ssl;

// Socket management
void openSocket();
void closeSocket();
bool readLineFromSocket(QByteArray&);
bool writeToSocket(const QString &);
};



Myclass.cpp :


MailChecker::MailChecker() : QObject()
{ sockect_ssl = new QSslSocket(this);

connect(sockect_ssl, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy & proxy, QAuthenticator * authenticator)),
this, SLOT(SLOT_socket_proxyAuthenticationRequired(const QNetworkProxy & proxy, QAuthenticator * authenticator)));
connect(sockect_ssl, SIGNAL(sslErrors(const QList<QSslError>)),this, SLOT(SLOT_socket_sslErrors(const QList<QSslError>)));
connect(sockect_ssl, SIGNAL(stateChanged), this, SLOT(SLOT_socket_stateChanged(QAbstractSocket::Soc ketState socketState)));
connect(sockect_ssl, SIGNAL(connected()), this, SLOT(SLOT_socket_connected()));
connect(sockect_ssl, SIGNAL(disconnected()),this, SLOT(SLOT_socket_disconnected()));
connect(sockect_ssl, SIGNAL(encrypted()), this, SLOT(SLOT_socket_encrypted()));
connect(sockect_ssl, SIGNAL(hostFound()), this, SLOT(SLOT_socket_hostFound()));
}
// ---------------------------------------------------------------------------------
void MailChecker::SLOT_socket_proxyAuthenticationRequir ed(const QNetworkProxy & proxy, QAuthenticator * authenticator)
{
cout << "PROXY AUTHENTIFICATION REQUIRED" << endl;
}

void MailChecker::SLOT_socket_sslErrors(const QList<QSslError> errors)
{
cout << "SSL ERRORS !" << endl;
}

void MailChecker::SLOT_socket_stateChanged(QAbstractSoc ket::SocketState socketState)
{
cout << "STATE CHANGED" << endl;
}

void MailChecker::SLOT_socket_connected()
{
cout << "CONNECTED" << endl;
}

void MailChecker::SLOT_socket_disconnected()
{
cout << "DISCONNECTED" << endl;
}

void MailChecker::SLOT_socket_encrypted()
{
cout << "ENCRYPTED" << endl;
}

void MailChecker::SLOT_socket_hostFound()
{
cout << "HOST FOUND" << endl;
}
// ---------------------------------------------------------------------------------
void MailChecker::openSocket()
{
sockect_ssl = new QSslSocket();
}

void MailChecker::closeSocket()
{
if ( sockect_ssl )
{
sockect_ssl->close();
sockect_ssl->deleteLater();
}
}

bool MailChecker::readLineFromSocket( QByteArray& data )
{
while ( !sockect_ssl->canReadLine() )
{
if ( !sockect_ssl->waitForReadyRead( 30 * 1000 ) )
{
closeSocket();
return 0;
}
}
if (sockect_ssl->readLine(data.data(), data.size()) == -1)
{
closeSocket();
return false;
}
return true;
}

bool MailChecker::writeToSocket( const QString & str )
{
QByteArray ba = str.toLocal8Bit();

qint64 wrote = 0;
while ( wrote < (qint64)ba.size() )
{
qint64 ret = sockect_ssl->write( ba.data() + wrote, ba.size() - wrote );
if ( ret == -1 )
return false; // error
wrote += ret;
}
sockect_ssl->waitForBytesWritten();
return true;
}

My first trouble is that the Slot are never called by my application... And they should be.
I don't understand why...



(1) Using the QSslSocket like a QTcpSocket (no encryption) :


void MailChecker::Check()
{
sockect_ssl->connectToHost(IMAP_host, IMAP_port);

if (sockect_ssl->waitForConnected(15000))
{
if (readLineFromSocket(line))
{
...
}
else
{
cout << "\n ERROR - Unable to read server response. " << endl;
}
}

This worked well for my old class using the QTcpSocket.
Now, this works well too, with the QSslSocket... But the data isn't encrypted.



(2) Using the QSslSocket with encryption :


void MailChecker::Check()
{
sockect_ssl->connectToHostEncrypted(IMAP_host, IMAP_port);

if (sockect_ssl->waitForConnected(15000))
{
if (readLineFromSocket(line))
{
...
}
else
{
cout << "\n ERROR - Unable to read server response. " << endl;
}
}

This should work. This is like the example given is the documentation...
But I get the ERROR message immediately : the socket hasn't waited for 15s. trying to connect to host with the encrypted mode.



(3) Using the QSslSocket with encryption :


void MailChecker::Check()
{
sockect_ssl->connectToHost(IMAP_host, IMAP_port);

if (sockect_ssl->waitForConnected(15000))
{
sockect_ssl->startClientEncryption();
if (readLineFromSocket(line))
{
...
}
else
{
cout << "\n ERROR - Unable to read server response. " << endl;
}
}

This is the sameThis code should do the same job as the (2) solution, but is provided for a TLS support. In my case, I get the ERROR like before, without any wait for connection.


If someone has an idea ?
Thanks :)

jacek
22nd June 2007, 22:57
My first trouble is that the Slot are never called by my application... And they should be.
Are there any messages on the console?

(You have to add "CONFIG += console" to the .pro file to see the console.)

Nyphel
26th June 2007, 14:36
The debug informations allowed me to adjust 3 connect declarations for my Signals/Slots... But they're still not called.

Moreover, for the following source code I get some debug advices :


sockect_ssl = new QSslSocket(this);



QSslSocket: cannot find ssleay32 library: QLibrary::load_sys: Cannot load ssleay32 (Le module spécifié est introuvable.).
QSslSocketBackendPrivate::ensureInitialized: unable to resolve all symbols
QSslSocket: cannot find ssleay32 library: QLibrary::load_sys: Cannot load ssleay32 (Le module spécifié est introuvable.).
QSslSocketBackendPrivate::ensureInitialized: unable to resolve all symbols
QSslSocket: cannot find ssleay32 library: QLibrary::load_sys: Cannot load ssleay32 (Le module spécifié est introuvable.).
QSslSocketBackendPrivate::ensureInitialized: unable to resolve all symbols
QSslSocket: cannot find ssleay32 library: QLibrary::load_sys: Cannot load ssleay32 (Le module spécifié est introuvable.).
QSslSocketBackendPrivate::ensureInitialized: unable to resolve all symbols
QSslSocket: cannot find ssleay32 library: QLibrary::load_sys: Cannot load ssleay32 (Le module spécifié est introuvable.).
QSslSocketBackendPrivate::ensureInitialized: unable to resolve all symbols


It seems that I should make a link between my app (and more generally Qt, because I would like to recompile it in -release -static modes) and the openSSL library... But I can't achieve to do that.

I suppose I shoul modifiy my .pro file, so did I, adding the following lines :


INCLUDEPATH += /openssl/include
LIBS += -L/openssl/lib ssleay32.lib libeay32.lib

But the console returns me :


C:\Qt\4.3.0\Workspace\Veilleur\SRC\MC_NB_mails>make
mingw32-make -f Makefile.Release
mingw32-make[1]: Entering directory `C:/Qt/4.3.0/Workspace/Veilleur/SRC/MC_NB_ma
ils'
g++ -enable-stdcall-fixup -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-rel
oc -Wl,-s -Wl,-subsystem,console -mthreads -Wl -o "release\MC_NB_mails.exe" tmp\
obj\release_shared\Gestion_comptes.o tmp\obj\release_shared\Gestion_liste_noire.
o tmp\obj\release_shared\MailChecker.o tmp\obj\release_shared\main.o tmp\obj\rel
ease_shared\MC_Logs.o tmp\obj\release_shared\moc_MailChecker.o -L"c:\Qt\4.3.0\l
ib" -L"c:\Qt\4.3.0\lib" ssleay32.lib -leay32.lib -lQtGui4 -lQtNetwork4 -lQtCore4

g++: ssleay32.lib: No such file or directory
mingw32-make[1]: *** [release\MC_NB_mails.exe] Error 1
mingw32-make[1]: Leaving directory `C:/Qt/4.3.0/Workspace/Veilleur/SRC/MC_NB_mai
ls'
mingw32-make: *** [release] Error 2

I get the same error with openSSL installed in "C:\" or "C:\Program Files\".
I've tried to create a new OPENSSLDIR environment variable, without success.



.

Nyphel
27th June 2007, 14:17
I've installed OpenSSL like this :

- C:\OpenSSL : the OpenSSL application directory
- C:\OpenSSL\lib\MinGW : the directory that contains the libs (ssleay32.a, ssleay32.def, libeay32.a and libeay32.def)
- C:\OpenSSL\include\openssl : the directory that contains the files to include, I suppose...

My MinGW compiler is in C:\MinGW.

Has someone an idea about linking the openSSL libs from my application, please ?