00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef TLSSOCKET_H
00023
00024 #include <QtCrypto>
00025 #include <QTcpSocket>
00026
00027 class TLSSocket : public QTcpSocket
00028 {
00029 public:
00030 TLSSocket(QObject *parent = 0);
00031 ~TLSSocket();
00032
00033 void connectToHostEncrypted(const QString &host, quint16 port);
00034 QCA::TLS *tls();
00035
00036 bool waitForReadyRead(int msecs = -1);
00037
00038 protected:
00039
00040 virtual qint64 readData(char *data, qint64 maxlen);
00041 virtual qint64 writeData(const char *data, qint64 len);
00042
00043 private:
00044 class Private;
00045 friend class Private;
00046 Private *d;
00047 };
00048
00049 #endif
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "tlssocket.h"
00023
00024 #include <QCoreApplication>
00025
00026 int main(int argc, char **argv)
00027 {
00028 QCA::Initializer init;
00029 QCoreApplication qapp(argc, argv);
00030
00031 TLSSocket socket;
00032 socket.connectToHostEncrypted("www.paypal.com", 443);
00033 socket.write("GET / HTTP/1.0\r\n\r\n");
00034 while(socket.waitForReadyRead())
00035 printf("%s", socket.readAll().data());
00036
00037 return 0;
00038 }
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "tlssocket.h"
00023
00024 class TLSSocket::Private : public QObject
00025 {
00026 Q_OBJECT
00027 public:
00028 TLSSocket *q;
00029 QTcpSocket *sock;
00030 QCA::TLS *tls;
00031 QString host;
00032 bool encrypted;
00033 bool error, done;
00034 QByteArray readbuf, writebuf;
00035 QCA::Synchronizer sync;
00036 bool waiting;
00037
00038 Private(TLSSocket *_q) : QObject(_q), q(_q), sync(_q)
00039 {
00040 sock = new QTcpSocket(this);
00041 connect(sock, SIGNAL(connected()), SLOT(sock_connected()));
00042 connect(sock, SIGNAL(readyRead()), SLOT(sock_readyRead()));
00043 connect(sock, SIGNAL(bytesWritten(qint64)), SLOT(sock_bytesWritten(qint64)));
00044 connect(sock, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(sock_error(QAbstractSocket::SocketError)));
00045
00046 tls = new QCA::TLS(this);
00047 connect(tls, SIGNAL(handshaken()), SLOT(tls_handshaken()));
00048 connect(tls, SIGNAL(readyRead()), SLOT(tls_readyRead()));
00049 connect(tls, SIGNAL(readyReadOutgoing()), SLOT(tls_readyReadOutgoing()));
00050 connect(tls, SIGNAL(closed()), SLOT(tls_closed()));
00051 connect(tls, SIGNAL(error()), SLOT(tls_error()));
00052 tls->setTrustedCertificates(QCA::systemStore());
00053 encrypted = false;
00054 error = false;
00055 waiting = false;
00056 done = false;
00057 }
00058
00059 bool waitForReadyRead(int msecs)
00060 {
00061 waiting = true;
00062 bool ok = sync.waitForCondition(msecs);
00063
00064
00065 waiting = false;
00066 if(error || done)
00067 return false;
00068 return ok;
00069 }
00070
00071 private slots:
00072 void sock_connected()
00073 {
00074
00075 tls->startClient(host);
00076 }
00077
00078 void sock_readyRead()
00079 {
00080
00081 QByteArray buf = sock->readAll();
00082
00083 tls->writeIncoming(buf);
00084 }
00085
00086 void sock_bytesWritten(qint64 x)
00087 {
00088 Q_UNUSED(x);
00089
00090 }
00091
00092 void sock_error(QAbstractSocket::SocketError x)
00093 {
00094
00095 Q_UNUSED(x);
00096 done = true;
00097 if(waiting)
00098 sync.conditionMet();
00099 }
00100
00101 void tls_handshaken()
00102 {
00103
00104 if(tls->peerIdentityResult() != QCA::TLS::Valid)
00105 {
00106 printf("not valid\n");
00107 sock->abort();
00108 tls->reset();
00109 error = true;
00110 }
00111 else
00112 {
00113
00114 encrypted = true;
00115
00116 if(!writebuf.isEmpty())
00117 {
00118
00119 tls->write(writebuf);
00120 writebuf.clear();
00121 }
00122 }
00123 if(waiting)
00124 sync.conditionMet();
00125 }
00126
00127 void tls_readyRead()
00128 {
00129
00130 if(waiting)
00131 sync.conditionMet();
00132 }
00133
00134 void tls_readyReadOutgoing()
00135 {
00136
00137 QByteArray buf = tls->readOutgoing();
00138
00139 sock->write(buf);
00140 }
00141
00142 void tls_closed()
00143 {
00144
00145 }
00146
00147 void tls_error()
00148 {
00149
00150 }
00151 };
00152
00153 TLSSocket::TLSSocket(QObject *parent)
00154 :QTcpSocket(parent)
00155 {
00156 d = new Private(this);
00157
00158 }
00159
00160 TLSSocket::~TLSSocket()
00161 {
00162 delete d;
00163 }
00164
00165 void TLSSocket::connectToHostEncrypted(const QString &host, quint16 port)
00166 {
00167 d->host = host;
00168 setOpenMode(QIODevice::ReadWrite);
00169 d->sock->connectToHost(host, port);
00170 }
00171
00172 QCA::TLS *TLSSocket::tls()
00173 {
00174 return d->tls;
00175 }
00176
00177 bool TLSSocket::waitForReadyRead(int msecs)
00178 {
00179
00180
00181
00182
00183
00184
00185 return d->waitForReadyRead(msecs);
00186 }
00187
00188 qint64 TLSSocket::readData(char *data, qint64 maxlen)
00189 {
00190 if(!d->error)
00191 d->readbuf += d->tls->read();
00192 unsigned char *p = (unsigned char *)d->readbuf.data();
00193 int size = d->readbuf.size();
00194 int readsize = qMin(size, (int)maxlen);
00195 int newsize = size - readsize;
00196 memcpy(data, p, readsize);
00197 memmove(p, p + readsize, newsize);
00198 d->readbuf.resize(newsize);
00199 return readsize;
00200 }
00201
00202 qint64 TLSSocket::writeData(const char *data, qint64 len)
00203 {
00204
00205 QByteArray buf(data, len);
00206 if(d->encrypted)
00207 d->tls->write(buf);
00208 else
00209 d->writebuf += buf;
00210 return len;
00211 }
00212
00213 #include "tlssocket.moc"