qca/examples/tlssocket/tlssocket.cpp
Justin Karneges 73d2a85ff7 tlssocket, just like qt 4.3 qsslsocket. okay not really yet
svn path=/trunk/kdesupport/qca/; revision=646994
2007-03-27 02:36:32 +00:00

193 lines
3.8 KiB
C++

#include "tlssocket.h"
class TLSSocket::Private : public QObject
{
Q_OBJECT
public:
TLSSocket *q;
QTcpSocket *sock;
QCA::TLS *tls;
QString host;
bool encrypted;
bool error, done;
QByteArray readbuf, writebuf;
QCA::Synchronizer sync;
bool waiting;
Private(TLSSocket *_q) : QObject(_q), q(_q), sync(_q)
{
sock = new QTcpSocket(this);
connect(sock, SIGNAL(connected()), SLOT(sock_connected()));
connect(sock, SIGNAL(readyRead()), SLOT(sock_readyRead()));
connect(sock, SIGNAL(bytesWritten(qint64)), SLOT(sock_bytesWritten(qint64)));
connect(sock, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(sock_error(QAbstractSocket::SocketError)));
tls = new QCA::TLS(this);
connect(tls, SIGNAL(handshaken()), SLOT(tls_handshaken()));
connect(tls, SIGNAL(readyRead()), SLOT(tls_readyRead()));
connect(tls, SIGNAL(readyReadOutgoing()), SLOT(tls_readyReadOutgoing()));
connect(tls, SIGNAL(closed()), SLOT(tls_closed()));
connect(tls, SIGNAL(error()), SLOT(tls_error()));
tls->setTrustedCertificates(QCA::systemStore());
encrypted = false;
error = false;
waiting = false;
done = false;
}
bool waitForReadyRead(int msecs)
{
waiting = true;
bool ok = sync.waitForCondition(msecs);
//while(1)
// QCoreApplication::instance()->processEvents();
waiting = false;
if(error || done)
return false;
return ok;
}
private slots:
void sock_connected()
{
//printf("sock connected\n");
tls->startClient(host);
}
void sock_readyRead()
{
//printf("sock ready read\n");
QByteArray buf = sock->readAll();
//printf("%d bytes\n", buf.size());
tls->writeIncoming(buf);
}
void sock_bytesWritten(qint64 x)
{
Q_UNUSED(x);
//printf("sock bytes written: %d\n", (int)x);
}
void sock_error(QAbstractSocket::SocketError x)
{
//printf("sock error: %d\n", x);
Q_UNUSED(x);
done = true;
if(waiting)
sync.conditionMet();
}
void tls_handshaken()
{
//printf("tls handshaken\n");
if(tls->peerIdentityResult() != QCA::TLS::Valid)
{
printf("not valid\n");
sock->abort();
tls->reset();
error = true;
}
else
{
//printf("valid\n");
encrypted = true;
//printf("%d bytes in writebuf\n", writebuf.size());
if(!writebuf.isEmpty())
{
//printf("[%s]\n", writebuf.data());
tls->write(writebuf);
writebuf.clear();
}
}
if(waiting)
sync.conditionMet();
}
void tls_readyRead()
{
//printf("tls ready read\n");
if(waiting)
sync.conditionMet();
}
void tls_readyReadOutgoing()
{
//printf("tls ready read outgoing\n");
QByteArray buf = tls->readOutgoing();
//printf("%d bytes\n", buf.size());
sock->write(buf);
}
void tls_closed()
{
//printf("tls closed\n");
}
void tls_error()
{
//printf("tls error\n");
}
};
TLSSocket::TLSSocket(QObject *parent)
:QTcpSocket(parent)
{
d = new Private(this);
}
TLSSocket::~TLSSocket()
{
delete d;
}
void TLSSocket::connectToHostEncrypted(const QString &host, quint16 port)
{
d->host = host;
setOpenMode(QIODevice::ReadWrite);
d->sock->connectToHost(host, port);
}
QCA::TLS *TLSSocket::tls()
{
return d->tls;
}
bool TLSSocket::waitForReadyRead(int msecs)
{
/*if(d->readbuf.isEmpty())
return false;
if(d->tls->bytesAvailable() == 0)
return false;*/
return d->waitForReadyRead(msecs);
}
qint64 TLSSocket::readData(char *data, qint64 maxlen)
{
if(!d->error)
d->readbuf += d->tls->read();
unsigned char *p = (unsigned char *)d->readbuf.data();
int size = d->readbuf.size();
int readsize = qMin(size, (int)maxlen);
int newsize = size - readsize;
memcpy(data, p, readsize);
memmove(p, p + readsize, newsize);
d->readbuf.resize(newsize);
return readsize;
}
qint64 TLSSocket::writeData(const char *data, qint64 len)
{
//printf("write %d bytes\n", (int)len);
QByteArray buf(data, len);
if(d->encrypted)
d->tls->write(buf);
else
d->writebuf += buf;
return len;
}
#include "tlssocket.moc"