~ubuntu-branches/ubuntu/jaunty/quassel/jaunty-backports

« back to all changes in this revision

Viewing changes to src/client/clientsyncer.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Scott Kitterman
  • Date: 2009-02-01 16:13:05 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20090201161305-ifle115wg2embbla
Tags: 0.4.0~git090201-0ubuntu1
* New upstream git snapshot
  - Core/client connection reliability improvements
  - Other bug fixing
* Adjust quassel-data.install to include ../oxygen/*/apps/quassel.svgz and
  quassel.png

Show diffs side-by-side

added added

removed removed

Lines of Context:
33
33
#include "util.h"
34
34
 
35
35
ClientSyncer::ClientSyncer(QObject *parent)
36
 
  : QObject(parent)
 
36
  : QObject(parent),
 
37
    _socket(0),
 
38
    _blockSize(0)
37
39
{
38
 
  socket = 0;
39
 
  blockSize = 0;
40
 
 
41
 
  connect(Client::signalProxy(), SIGNAL(disconnected()), this, SLOT(coreSocketDisconnected()));
42
40
}
43
41
 
44
42
ClientSyncer::~ClientSyncer() {
46
44
 
47
45
void ClientSyncer::coreHasData() {
48
46
  QVariant item;
49
 
  while(SignalProxy::readDataFromDevice(socket, blockSize, item)) {
 
47
  while(SignalProxy::readDataFromDevice(_socket, _blockSize, item)) {
50
48
    emit recvPartialItem(1,1);
51
49
    QVariantMap msg = item.toMap();
52
50
    if(!msg.contains("MsgType")) {
81
79
      return;
82
80
    }
83
81
  }
84
 
  if(blockSize > 0) {
85
 
    emit recvPartialItem(socket->bytesAvailable(), blockSize);
 
82
  if(_blockSize > 0) {
 
83
    emit recvPartialItem(_socket->bytesAvailable(), _blockSize);
86
84
  }
87
85
}
88
86
 
89
87
void ClientSyncer::coreSocketError(QAbstractSocket::SocketError) {
90
 
  qDebug() << "coreSocketError" << socket << socket->errorString();
91
 
  emit connectionError(socket->errorString());
92
 
  socket->deleteLater();
 
88
  qDebug() << "coreSocketError" << _socket << _socket->errorString();
 
89
  emit connectionError(_socket->errorString());
 
90
  resetConnection();
93
91
}
94
92
 
95
93
void ClientSyncer::disconnectFromCore() {
96
 
  if(socket) socket->close();
 
94
  if(_socket)
 
95
    _socket->close();
 
96
  resetConnection();
97
97
}
98
98
 
99
99
void ClientSyncer::connectToCore(const QVariantMap &conn) {
100
 
  // TODO implement SSL
 
100
  resetConnection();
101
101
  coreConnectionInfo = conn;
102
 
  //if(isConnected()) {
103
 
  //  emit coreConnectionError(tr("Already connected to Core!"));
104
 
  //  return;
105
 
  // }
106
 
  if(socket != 0) {
107
 
    socket->deleteLater();
108
 
    socket = 0;
109
 
  }
 
102
 
110
103
  if(conn["Host"].toString().isEmpty()) {
111
 
    emit connectionError(tr("Internal connections not yet supported."));
112
 
    return; // FIXME implement internal connections
113
 
    //clientMode = LocalCore;
114
 
    socket = new QBuffer(this);
115
 
    connect(socket, SIGNAL(readyRead()), this, SLOT(coreHasData()));
116
 
    socket->open(QIODevice::ReadWrite);
117
 
    //QVariant state = connectToLocalCore(coreConnectionInfo["User"].toString(), coreConnectionInfo["Password"].toString());
118
 
    //syncToCore(state);
119
 
    coreSocketConnected();
120
 
  } else {
121
 
    //clientMode = RemoteCore;
122
 
    //emit coreConnectionMsg(tr("Connecting..."));
123
 
    Q_ASSERT(!socket);
 
104
    emit connectionError(tr("No Host to connect to specified."));
 
105
    return;
 
106
  }
124
107
 
 
108
  Q_ASSERT(!_socket);
125
109
#ifdef HAVE_SSL
126
 
    QSslSocket *sock = new QSslSocket(Client::instance());
127
 
    connect(sock, SIGNAL(encrypted()), this, SIGNAL(encrypted()));
 
110
  QSslSocket *sock = new QSslSocket(Client::instance());
128
111
#else
129
 
    if(conn["useSsl"].toBool()) {
130
 
        emit connectionError(tr("<b>This client is built without SSL Support!</b><br />Disable the usage of SSL in the account settings."));
131
 
        return;
132
 
    }
133
 
    QTcpSocket *sock = new QTcpSocket(Client::instance());
 
112
  if(conn["useSsl"].toBool()) {
 
113
    emit connectionError(tr("<b>This client is built without SSL Support!</b><br />Disable the usage of SSL in the account settings."));
 
114
    return;
 
115
  }
 
116
  QTcpSocket *sock = new QTcpSocket(Client::instance());
134
117
#endif
 
118
 
135
119
#ifndef QT_NO_NETWORKPROXY
136
 
    if(conn.contains("useProxy") && conn["useProxy"].toBool()) {
137
 
      QNetworkProxy proxy((QNetworkProxy::ProxyType)conn["proxyType"].toInt(), conn["proxyHost"].toString(), conn["proxyPort"].toUInt(), conn["proxyUser"].toString(), conn["proxyPassword"].toString());
138
 
      sock->setProxy(proxy);
139
 
    }
 
120
  if(conn.contains("useProxy") && conn["useProxy"].toBool()) {
 
121
    QNetworkProxy proxy((QNetworkProxy::ProxyType)conn["proxyType"].toInt(), conn["proxyHost"].toString(), conn["proxyPort"].toUInt(), conn["proxyUser"].toString(), conn["proxyPassword"].toString());
 
122
    sock->setProxy(proxy);
 
123
  }
140
124
#endif
141
 
    socket = sock;
142
 
    connect(sock, SIGNAL(readyRead()), this, SLOT(coreHasData()));
143
 
    connect(sock, SIGNAL(connected()), this, SLOT(coreSocketConnected()));
144
 
    connect(sock, SIGNAL(disconnected()), this, SLOT(coreSocketDisconnected()));
145
 
    connect(sock, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(coreSocketError(QAbstractSocket::SocketError)));
146
 
    connect(sock, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SIGNAL(socketStateChanged(QAbstractSocket::SocketState)));
147
 
    sock->connectToHost(conn["Host"].toString(), conn["Port"].toUInt());
148
 
  }
 
125
 
 
126
  _socket = sock;
 
127
  connect(sock, SIGNAL(readyRead()), this, SLOT(coreHasData()));
 
128
  connect(sock, SIGNAL(connected()), this, SLOT(coreSocketConnected()));
 
129
  connect(sock, SIGNAL(disconnected()), this, SLOT(coreSocketDisconnected()));
 
130
  connect(sock, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(coreSocketError(QAbstractSocket::SocketError)));
 
131
  connect(sock, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SIGNAL(socketStateChanged(QAbstractSocket::SocketState)));
 
132
  sock->connectToHost(conn["Host"].toString(), conn["Port"].toUInt());
149
133
}
150
134
 
151
135
void ClientSyncer::coreSocketConnected() {
165
149
  clientInit["UseCompression"] = false;
166
150
#endif
167
151
 
168
 
  SignalProxy::writeDataToDevice(socket, clientInit);
 
152
  SignalProxy::writeDataToDevice(_socket, clientInit);
169
153
}
170
154
 
171
155
void ClientSyncer::useInternalCore() {
202
186
 
203
187
void ClientSyncer::coreSocketDisconnected() {
204
188
  emit socketDisconnected();
205
 
  Client::instance()->disconnectFromCore();
206
 
 
207
 
  // FIXME handle disconnects gracefully in here as well!
208
 
 
209
 
  coreConnectionInfo.clear();
210
 
  netsToSync.clear();
211
 
  blockSize = 0;
212
 
  //restartPhaseNull();
 
189
  resetConnection();
 
190
  // FIXME handle disconnects gracefully
213
191
}
214
192
 
215
193
void ClientSyncer::clientInitAck(const QVariantMap &msg) {
225
203
 
226
204
#ifndef QT_NO_COMPRESS
227
205
  if(msg["SupportsCompression"].toBool()) {
228
 
    socket->setProperty("UseCompression", true);
 
206
    _socket->setProperty("UseCompression", true);
229
207
  }
230
208
#endif
231
209
 
233
211
#ifdef HAVE_SSL
234
212
  if(coreConnectionInfo["useSsl"].toBool()) {
235
213
    if(msg["SupportSsl"].toBool()) {
236
 
      QSslSocket *sslSocket = qobject_cast<QSslSocket *>(socket);
 
214
      QSslSocket *sslSocket = qobject_cast<QSslSocket *>(_socket);
237
215
      Q_ASSERT(sslSocket);
238
216
      connect(sslSocket, SIGNAL(encrypted()), this, SLOT(sslSocketEncrypted()));
239
217
      connect(sslSocket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(sslErrors(const QList<QSslError> &)));
265
243
  QVariantMap setup;
266
244
  setup["MsgType"] = "CoreSetupData";
267
245
  setup["SetupData"] = setupData;
268
 
  SignalProxy::writeDataToDevice(socket, setup);
 
246
  SignalProxy::writeDataToDevice(_socket, setup);
269
247
}
270
248
 
271
249
void ClientSyncer::loginToCore(const QString &user, const QString &passwd) {
274
252
  clientLogin["MsgType"] = "ClientLogin";
275
253
  clientLogin["User"] = user;
276
254
  clientLogin["Password"] = passwd;
277
 
  SignalProxy::writeDataToDevice(socket, clientLogin);
 
255
  SignalProxy::writeDataToDevice(_socket, clientLogin);
278
256
}
279
257
 
280
258
void ClientSyncer::internalSessionStateReceived(const QVariant &packedState) {
287
265
void ClientSyncer::sessionStateReceived(const QVariantMap &state) {
288
266
  emit sessionProgress(1, 1);
289
267
  disconnect(this, SIGNAL(recvPartialItem(quint32, quint32)), this, SIGNAL(sessionProgress(quint32, quint32)));
290
 
  disconnect(socket, 0, this, 0);  // rest of communication happens through SignalProxy
291
 
  Client::instance()->setConnectedToCore(coreConnectionInfo["AccountId"].value<AccountId>(), socket);
 
268
 
 
269
  // rest of communication happens through SignalProxy...
 
270
  disconnect(_socket, 0, this, 0);
 
271
  // ... but we still want to be notified about errors...
 
272
  connect(_socket, SIGNAL(disconnected()), this, SLOT(coreSocketDisconnected()));
 
273
  connect(_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(coreSocketError(QAbstractSocket::SocketError)));
 
274
 
 
275
  Client::instance()->setConnectedToCore(coreConnectionInfo["AccountId"].value<AccountId>(), _socket);
292
276
  syncToCore(state);
293
277
}
294
278
 
348
332
  disconnect(this, SIGNAL(handleIgnoreWarnings(bool)), this, 0);
349
333
}
350
334
 
 
335
void ClientSyncer::resetConnection() {
 
336
  if(_socket) {
 
337
    disconnect(_socket, 0, this, 0);
 
338
    _socket->deleteLater();
 
339
    _socket = 0;
 
340
  }
 
341
  _blockSize = 0;
 
342
 
 
343
  coreConnectionInfo.clear();
 
344
  _coreMsgBuffer.clear();
 
345
 
 
346
  netsToSync.clear();
 
347
  numNetsToSync = 0;
 
348
}
 
349
 
351
350
#ifdef HAVE_SSL
352
351
void ClientSyncer::ignoreSslWarnings(bool permanently) {
353
 
  QSslSocket *sock = qobject_cast<QSslSocket *>(socket);
 
352
  QSslSocket *sock = qobject_cast<QSslSocket *>(_socket);
354
353
  if(sock) {
355
354
    // ensure that a proper state is displayed and no longer a warning
356
355
    emit socketStateChanged(sock->state());
367
366
 
368
367
void ClientSyncer::sslSocketEncrypted() {
369
368
  QSslSocket *socket = qobject_cast<QSslSocket *>(sender());
370
 
  if(socket) {
371
 
    QByteArray digest = socket->peerCertificate().digest();
372
 
  }
 
369
  Q_ASSERT(socket);
 
370
 
 
371
  // if there were sslErrors we already had extensive error handling
 
372
  // no need to check for a digest change again.
 
373
  if(!socket->sslErrors().isEmpty())
 
374
    return;
 
375
 
 
376
  QByteArray knownDigest = KnownHostsSettings().knownDigest(socket);
 
377
  if(knownDigest == socket->peerCertificate().digest()) {
 
378
    connectionReady();
 
379
    return;
 
380
  }
 
381
 
 
382
  QStringList warnings;
 
383
  if(!knownDigest.isEmpty()) {
 
384
    warnings << tr("Cert Digest changed! was: %1").arg(QString(prettyDigest(knownDigest)));
 
385
  }
 
386
 
 
387
  setWarningsHandler(SLOT(ignoreSslWarnings(bool)));
 
388
  emit connectionWarnings(warnings);
373
389
}
374
390
 
375
391
void ClientSyncer::sslErrors(const QList<QSslError> &errors) {
376
 
  QByteArray knownDigest;
377
392
  QSslSocket *socket = qobject_cast<QSslSocket *>(sender());
378
 
  if(socket) {
379
 
    socket->ignoreSslErrors();
380
 
    knownDigest = KnownHostsSettings().knownDigest(socket);
381
 
    if(knownDigest == socket->peerCertificate().digest()) {
382
 
      connectionReady();
383
 
      return;
384
 
    }
 
393
  Q_ASSERT(socket);
 
394
 
 
395
  socket->ignoreSslErrors();
 
396
 
 
397
  QByteArray knownDigest = KnownHostsSettings().knownDigest(socket);
 
398
  if(knownDigest == socket->peerCertificate().digest()) {
 
399
    connectionReady();
 
400
    return;
385
401
  }
386
402
 
387
403
  QStringList warnings;