📄 qtsslsocket.cpp
字号:
/******************************************************************************** Copyright (C) 2000-2006 TROLLTECH ASA. All rights reserved.**** This file is part of the Phone Edition of the Qtopia Toolkit.**** Licensees holding a valid license agreement from Trolltech or any of its** authorized distributors may use this file in accordance with** the License Agreement provided with the Licensed Software.**** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for** information about Trolltech's Commercial License Agreements.**** Contact info@trolltech.com if any conditions of this licensing are** not clear to you.********** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************///#define QTSSLSOCKET_DEBUG#include "qtsslsocket.h"#include <QtCore/QDateTime>#include <QtCore/QDebug>#include <QtCore/QFile>#include <QtCore/QList>#include <QtCore/QStringList>#include <QtCore/QTimer>#include <QtNetwork/QHostAddress>#include <qtopia/qtopianamespace.h>// OpenSSL includes#include "ssllibrary.h"//#endifconst int SslReadBlockSize = 4096;#define SSL_ERRORSTR() lib->ERR_error_string(lib->ERR_get_error(), NULL)class QtRingBuffer{public: QtRingBuffer(int growth = 4096); int nextDataBlockSize() const; char *readPointer() const; void free(int bytes); char *reserve(int bytes); void truncate(int bytes); bool isEmpty() const; int getChar(); void putChar(char c); void ungetChar(char c); int size() const; void clear(); int indexOf(char c) const; int readLine(char *data, int maxLength); bool canReadLine() const;private: QList<QByteArray> buffers; int head, tail; int tailBuffer; int basicBlockSize; int bufferSize;};/*! \internal Creates an empty ring buffer. The buffer will grow in steps of \a growth as data is written to it.*/QtRingBuffer::QtRingBuffer(int growth) : basicBlockSize(growth){ buffers << QByteArray(); clear();}/*! \internal Returns the number of bytes that can be read in one operation. The data is read from readPointer().*/int QtRingBuffer::nextDataBlockSize() const{ return (tailBuffer == 0 ? tail : buffers.at(0).size()) - head;}/*! \internal Returns a pointer to where no more than nextDataBlockSize() bytes of data can be read. Call free() to remove data after reading.*/char *QtRingBuffer::readPointer() const{ if (buffers.count() == 0) return 0; return const_cast<char *>(buffers[0].data()) + head;}/*! \internal Removes \a bytes bytes from the front of the buffer. If \a bytes is larger than the size of the buffer, the buffer is cleared.*/void QtRingBuffer::free(int bytes){ bufferSize -= bytes; if (bufferSize < 0) bufferSize = 0; for (;;) { int nextBlockSize = nextDataBlockSize(); if (bytes < nextBlockSize) { head += bytes; if (head == tail && tailBuffer == 0) head = tail = 0; return; } bytes -= nextBlockSize; if (buffers.count() == 1) { if (buffers.at(0).size() != basicBlockSize) buffers[0].resize(basicBlockSize); head = tail = 0; tailBuffer = 0; return; } buffers.removeAt(0); --tailBuffer; head = 0; }}/*! \internal Reserves space in the buffer for \a bytes new bytes, and returns a pointer to the first byte.*/char *QtRingBuffer::reserve(int bytes){ bufferSize += bytes; // if there is already enough space, simply return. if (tail + bytes <= buffers.at(tailBuffer).size()) { char *writePtr = buffers[tailBuffer].data() + tail; tail += bytes; return writePtr; } // if our buffer isn't half full yet, simply resize it. if (tail < buffers.at(tailBuffer).size() / 2) { buffers[tailBuffer].resize(tail + bytes); char *writePtr = buffers[tailBuffer].data() + tail; tail += bytes; return writePtr; } // shrink this buffer to its current size buffers[tailBuffer].resize(tail); // create a new QByteArray with the right size buffers << QByteArray(); ++tailBuffer; buffers[tailBuffer].resize(qMax(basicBlockSize, bytes)); tail = bytes; return buffers[tailBuffer].data();}/*! \internal Removes \a bytes bytes from the end of the buffer. If \a bytes is larger than the buffer size, the buffer is cleared.*/void QtRingBuffer::truncate(int bytes){ bufferSize -= bytes; if (bufferSize < 0) bufferSize = 0; for (;;) { // special case: head and tail are in the same buffer if (tailBuffer == 0) { tail -= bytes; if (tail <= head) tail = head = 0; return; } if (bytes <= tail) { tail -= bytes; return; } bytes -= tail; buffers.removeAt(tailBuffer); --tailBuffer; tail = buffers.at(tailBuffer).size(); }}/*! \internal Returns and removes the first character in the buffer. Returns -1 if the buffer is empty.*/int QtRingBuffer::getChar(){ if (isEmpty()) return -1; char c = *readPointer(); free(1); return c;}/*! \internal Appends the character \a c to the end of the buffer.*/void QtRingBuffer::putChar(char c){ char *ptr = reserve(1); *ptr = c;}/*! \internal Prepends the character \a c to the front of the buffer.*/void QtRingBuffer::ungetChar(char c){ --head; if (head < 0) { buffers.prepend(QByteArray()); buffers[0].resize(basicBlockSize); head = basicBlockSize - 1; ++tailBuffer; } buffers[0][head] = c; ++bufferSize;}/*! \internal Returns the size of the buffer; e.g. the number of bytes currently in use.*/int QtRingBuffer::size() const{ return bufferSize;}/*! \internal Removes all data from the buffer and resets its size to 0.*/void QtRingBuffer::clear(){ QByteArray tmp = buffers[0]; buffers.clear(); buffers << tmp; if (buffers.at(0).size() != basicBlockSize) buffers[0].resize(basicBlockSize); head = tail = 0; tailBuffer = 0; bufferSize = 0;}/*! \internal Returns true if the buffer is empty; otherwise returns false.*/bool QtRingBuffer::isEmpty() const{ return tailBuffer == 0 && tail == 0;}/*! \internal Returns the index of the first occurrence of the character \a c in the buffer. In no such character is found, -1 is returned.*/int QtRingBuffer::indexOf(char c) const{ int index = 0; for (int i = 0; i < buffers.size(); ++i) { int start = 0; int end = buffers.at(i).size(); if (i == 0) start = head; if (i == tailBuffer) end = tail; const char *ptr = buffers.at(i).data() + start; for (int j = start; j < end; ++j) { if (*ptr++ == c) return index; ++index; } } return -1;}/*! \internal Reads one line of data (all data up to and including the '\\n' character), no longer than \a maxSize - 1 bytes, and stores it in \a data. If the line is too long, maxSize bytes of the line are read. \a data is always terminated by a '\\0' byte.*/int QtRingBuffer::readLine(char *data, int maxSize){ int index = indexOf('\n'); if (index == -1 || maxSize <= 0) return -1; int readSoFar = 0; while (readSoFar < index && readSoFar < maxSize - 1) { int bytesToRead = qMin((index + 1) - readSoFar, nextDataBlockSize()); bytesToRead = qMin(bytesToRead, (maxSize - 1) - readSoFar); memcpy(data + readSoFar, readPointer(), bytesToRead); readSoFar += bytesToRead; free(bytesToRead); } // Terminate it. data[readSoFar] = '\0'; return readSoFar;}/*! \internal Returns true if a line can be read from the buffer; otherwise returns false.*/bool QtRingBuffer::canReadLine() const{ return indexOf('\n') != -1;}class QtSslSocketPrivate{public: QtSslSocketPrivate(QtSslSocket *qq); void initializeConnection(QTcpSocket *socket); QtRingBuffer readBuffer; QtRingBuffer writeBuffer; bool connectionSecured; QTcpSocket *socket; QtSslSocket::Mode mode; bool initialized; bool calledWriteToSocket; bool readyReadEmitted; // SSL context SSL *ssl; SSL_CTX *ctx; BIO *rbio; BIO *wbio; QString cert; QString certDir; QString key; QString cafile; QString cadir; QString ciph; QtSslSocket *q;};QtSslSocketPrivate::QtSslSocketPrivate(QtSslSocket *qq) : connectionSecured(false), socket(0), mode(QtSslSocket::Client), initialized(false), calledWriteToSocket(false), readyReadEmitted(false), ssl(0), ctx(0), rbio(0), wbio(0), q(qq){}void QtSslSocketPrivate::initializeConnection(QTcpSocket *socket){ socket->disconnect(); QObject::connect(socket, SIGNAL(connected()), q, SLOT(sslConnect())); QObject::connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), q, SLOT(handleSocketError(QAbstractSocket::SocketError))); QObject::connect(socket, SIGNAL(disconnected()), q, SIGNAL(disconnected())); QObject::connect(socket, SIGNAL(readyRead()), q, SLOT(readFromSocket())); QObject::connect(socket, SIGNAL(bytesWritten(qint64)), q, SLOT(socketBytesWritten(qint64)));}/*! \class QtSslSocket \brief The QtSslSocket class provides a TCP socket with SSL encryption support. It provides some extra functionality which is needed for working with SSL, but otherwise there is no difference from QTcpSocket. Example: \code void MyClient::connectToHost(const QString &host, int port) { // Create a new SSL socket socket = new QtSslSocket();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -