00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "Papillon/Network/IpEndpointConnector"
00019 #include "Papillon/Network/NetworkStream"
00020 #include <QtGlobal>
00021 #include <QtNetwork/QNetworkProxy>
00022 #include <QtNetwork/QSslSocket>
00023 #include <QtDebug>
00024
00025 namespace Papillon
00026 {
00027
00028 class IpEndpointConnector::IpEndpointConnectorPrivate
00029 {
00030 public:
00031 IpEndpointConnectorPrivate() : connectorState(IpEndpointConnector::Created),
00032 port(0), underlyingSocketUsesTls(false) {}
00033
00034 IpEndpointConnector::State connectorState;
00035 QString ipAddress;
00036 NetworkStream *networkStream;
00037 quint16 port;
00038 QSslSocket *socket;
00039 bool underlyingSocketUsesTls;
00040 };
00041
00042 IpEndpointConnector::IpEndpointConnector(bool enableTls, QObject *parent) : QObject(parent), d(new IpEndpointConnectorPrivate())
00043 {
00044 d->underlyingSocketUsesTls = enableTls;
00045
00046 d->socket = new QSslSocket(this);
00047
00048 d->socket->setProxy(QNetworkProxy::applicationProxy());
00049
00050 d->socket->setReadBufferSize(4096);
00051
00052 d->networkStream = new NetworkStream(d->socket, false, this);
00053 }
00054
00055 IpEndpointConnector::~IpEndpointConnector()
00056 {
00057 delete d;
00058 d = 0l;
00059 }
00060
00061 NetworkStream * IpEndpointConnector::networkStream()
00062 {
00063 return state() == IpEndpointConnector::Connected ? d->networkStream : 0l;
00064 }
00065
00066 const IpEndpointConnector::State & IpEndpointConnector::state() const
00067 {
00068 return d->connectorState;
00069 }
00070
00071 void IpEndpointConnector::close()
00072 {
00073 if (d->connectorState != IpEndpointConnector::Closing ||
00074 d->connectorState != IpEndpointConnector::Closed)
00075 {
00076
00077 d->connectorState = IpEndpointConnector::Closing;
00078
00079 emit closing();
00080
00081 if (d->socket->state() != QSslSocket::UnconnectedState)
00082 {
00083
00084
00085 d->socket->close();
00086 }
00087 else
00088 {
00089 qDebug("%s: Closing synchronously", Q_FUNC_INFO);
00090
00091
00092 closeConnector();
00093 }
00094 }
00095 }
00096
00097 void IpEndpointConnector::connectWithAddressInfo(const QString& ipAddress, const quint16 port)
00098 {
00099 if (d->connectorState == IpEndpointConnector::Faulted ||
00100 d->connectorState == IpEndpointConnector::Closing)
00101 {
00102 return;
00103 }
00104
00105 if (d->connectorState != IpEndpointConnector::Connected ||
00106 d->connectorState != IpEndpointConnector::Connecting)
00107 {
00108 d->ipAddress = ipAddress;
00109 d->port = port;
00110
00111
00112 QObject::connect(d->socket, SIGNAL(connected()), this,
00113 SLOT(socket_OnConnect()));
00114 QObject::connect(d->socket, SIGNAL(error(QAbstractSocket::SocketError)), this,
00115 SLOT(socket_OnError(QAbstractSocket::SocketError)));
00116 QObject::connect(d->socket, SIGNAL(disconnected()), this,
00117 SLOT(socket_OnClose()));
00118
00119
00120 d->connectorState = IpEndpointConnector::Connecting;
00121
00122 qDebug("%s: Connecting to (addr=%s port=%d)", Q_FUNC_INFO,
00123 qPrintable(ipAddress), port);
00124
00125
00126 emit connecting();
00127
00128
00129 d->socket->connectToHost(ipAddress, port);
00130 }
00131 }
00132
00133 void IpEndpointConnector::closeConnector()
00134 {
00135
00136 d->networkStream->close();
00137
00138 d->connectorState = IpEndpointConnector::Closed;
00139
00140 emit closed();
00141 }
00142
00143
00144
00145 void IpEndpointConnector::socket_OnClose()
00146 {
00147
00148 QObject::disconnect(d->socket, 0, this, 0);
00149
00150 qDebug("%s: Connection to (addr=%s port=%d) closed", Q_FUNC_INFO,
00151 qPrintable(d->ipAddress), d->port);
00152
00153
00154 closeConnector();
00155 }
00156
00157 void IpEndpointConnector::socket_OnConnect()
00158 {
00159
00160 d->connectorState = IpEndpointConnector::Connected;
00161
00162 qDebug("%s: Connected to (addr=%s port=%d)", Q_FUNC_INFO,
00163 qPrintable(d->ipAddress), d->port);
00164
00165 if (d->underlyingSocketUsesTls)
00166 {
00167
00168
00169 QObject::connect(d->socket, SIGNAL(encrypted()), this,
00170 SLOT(socket_OnTlsConnect()));
00171 QObject::connect(d->socket, SIGNAL(sslErrors(const QList<QSslError>&)), this,
00172 SLOT(socket_OnTlsError(const QList<QSslError>&)));
00173
00174 qDebug("%s: starting client authentication.", Q_FUNC_INFO);
00175
00176 d->socket->startClientEncryption();
00177 }
00178 else
00179 {
00180
00181 emit connected();
00182 }
00183 }
00184
00185 void IpEndpointConnector::socket_OnError(QAbstractSocket::SocketError socketError)
00186 {
00187 Q_UNUSED(socketError);
00188
00189
00190 d->connectorState = IpEndpointConnector::Faulted;
00191
00192 qDebug("%s: error=%s", Q_FUNC_INFO, qPrintable(d->socket->errorString()));
00193
00194
00195 QObject::disconnect(d->socket, SIGNAL(error(QAbstractSocket::SocketError)), this,
00196 SLOT(socket_OnError(QAbstractSocket::SocketError)));
00197
00198
00199 emit faulted();
00200 }
00201
00202 void IpEndpointConnector::socket_OnTlsConnect()
00203 {
00204 qDebug("%s: network stream is now encrypted.", Q_FUNC_INFO);
00205
00206
00207 emit connected();
00208 }
00209
00210 void IpEndpointConnector::socket_OnTlsError(const QList<QSslError>& errors)
00211 {
00212
00213 d->connectorState = IpEndpointConnector::Faulted;
00214
00215
00216 QObject::disconnect(d->socket, SIGNAL(sslErrors(const QList<QSslError>&)), this,
00217 SLOT(socket_OnTlsError(const QList<QSslError>&)));
00218
00219 QSslError error;
00220 foreach(error, errors)
00221 {
00222 qDebug("%s: error=%s", Q_FUNC_INFO, qPrintable(error.errorString()));
00223 }
00224
00225
00226 emit faulted();
00227 }
00228
00229
00230
00231 }
00232
00233 #include "ipendpointconnector.moc"