00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <QCoreApplication>
00019 #include <QMutexLocker>
00020 #include <stringutil.h>
00021 #include "tcglobal.h"
00022
00023 #include "controlconnection.h"
00024
00025
00026 #define MAX_CONNECT_ATTEMPTS 5
00027
00028 #define CONNECT_RETRY_DELAY 2*1000
00029
00030
00031
00032 ControlConnection::ControlConnection(TorEvents *events)
00033 {
00034 _events = events;
00035 _status = Unset;
00036 _sock = 0;
00037 _sendWaiter = new SendCommandEvent::SendWaiter();
00038 }
00039
00040
00041 ControlConnection::~ControlConnection()
00042 {
00043
00044 exit();
00045
00046 wait();
00047
00048 delete _sendWaiter;
00049 }
00050
00051
00052 void
00053 ControlConnection::connect(const QHostAddress &addr, quint16 port)
00054 {
00055 if (isRunning()) {
00056 tc::error("Bug: Tried to call ControlConnection::connect() when the "
00057 "control thread is already running.");
00058 return;
00059 }
00060
00061
00062 _addr = addr;
00063 _port = port;
00064 _sock = 0;
00065 _connectAttempt = 0;
00066 setStatus(Connecting);
00067
00068
00069 QThread::start();
00070 }
00071
00072
00073
00074
00075 void
00076 ControlConnection::connect()
00077 {
00078 _connectAttempt++;
00079 tc::debug("Connecting to Tor (Attempt %1 of %2)").arg(_connectAttempt)
00080 .arg(MAX_CONNECT_ATTEMPTS);
00081
00082 _connMutex.lock();
00083 _sock->connectToHost(_addr, _port);
00084 _connMutex.unlock();
00085 }
00086
00087
00088 void
00089 ControlConnection::disconnect()
00090 {
00091 setStatus(Disconnecting);
00092 _connMutex.lock();
00093 _sock->disconnectFromHost();
00094 _connMutex.unlock();
00095 }
00096
00097
00098
00099 void
00100 ControlConnection::onConnected()
00101 {
00102 setStatus(Connected);
00103 emit connected();
00104 }
00105
00106
00107
00108 void
00109 ControlConnection::onDisconnected()
00110 {
00111 setStatus(Disconnected);
00112 emit disconnected();
00113 exit(0);
00114 }
00115
00116
00117 void
00118 ControlConnection::onError(QAbstractSocket::SocketError error)
00119 {
00120 if (status() == Connecting) {
00121
00122
00123
00124 if (error == QAbstractSocket::ConnectionRefusedError &&
00125 _connectAttempt < MAX_CONNECT_ATTEMPTS) {
00126 tc::debug("Control connection refused. Retrying in %1ms.")
00127 .arg(CONNECT_RETRY_DELAY);
00128 _connectTimer->start(CONNECT_RETRY_DELAY);
00129 } else {
00130
00131 QString errstr = ControlSocket::toString(error);
00132 tc::error("Vidalia was unable to connect to Tor: %1").arg(errstr);
00133 emit connectFailed(tr("Vidalia was unable to connect to Tor. (%1)")
00134 .arg(errstr));
00135 setStatus(Disconnected);
00136 }
00137 } else if (error == QAbstractSocket::RemoteHostClosedError) {
00138
00139
00140 tc::warn("Tor closed the control connection.");
00141 } else {
00142
00143
00144
00145 tc::error("Control socket error: %1").arg(ControlSocket::toString(error));
00146 }
00147 }
00148
00149
00150 void
00151 ControlConnection::cancelConnect()
00152 {
00153 tc::warn("Control connection attempt cancelled.");
00154 setStatus(Disconnected);
00155 exit(0);
00156 }
00157
00158
00159 bool
00160 ControlConnection::isConnected()
00161 {
00162 return (status() == Connected);
00163 }
00164
00165
00166 ControlConnection::Status
00167 ControlConnection::status()
00168 {
00169 QMutexLocker locker(&_statusMutex);
00170 return _status;
00171 }
00172
00173
00174
00175 QString
00176 ControlConnection::statusString(Status status)
00177 {
00178 QString str;
00179 switch (status) {
00180 case Unset: str = "Unset"; break;
00181 case Disconnected: str = "Disconnected"; break;
00182 case Disconnecting: str = "Disconnecting"; break;
00183 case Connecting: str = "Connecting"; break;
00184 case Connected: str = "Connected"; break;
00185 default: str = "unknown";
00186 }
00187 return str;
00188 }
00189
00190
00191 void
00192 ControlConnection::setStatus(Status status)
00193 {
00194 QMutexLocker locker(&_statusMutex);
00195 tc::debug("Control connection status changed from '%1' to '%2'")
00196 .arg(statusString(_status))
00197 .arg(statusString(status));
00198 _status = status;
00199 }
00200
00201
00202 bool
00203 ControlConnection::send(const ControlCommand &cmd,
00204 ControlReply &reply, QString *errmsg)
00205 {
00206 bool result = false;
00207 QString errstr;
00208
00209 _recvMutex.lock();
00210 if (send(cmd, &errstr)) {
00211
00212 ReceiveWaiter *w = new ReceiveWaiter();
00213 _recvQueue.enqueue(w);
00214 _recvMutex.unlock();
00215
00216
00217 result = w->getResult(&reply, &errstr);
00218 if (!result)
00219 tc::error("Failed to receive control reply: %1").arg(errstr);
00220 delete w;
00221 } else {
00222 tc::error("Failed to send control command (%1): %2").arg(cmd.keyword())
00223 .arg(errstr);
00224 _recvMutex.unlock();
00225 }
00226
00227 if (!result && errmsg)
00228 *errmsg = errstr;
00229 return result;
00230 }
00231
00232
00233
00234
00235 bool
00236 ControlConnection::send(const ControlCommand &cmd, QString *errmsg)
00237 {
00238 _connMutex.lock();
00239 if (!_sock || !_sock->isConnected()) {
00240 _connMutex.unlock();
00241 return err(errmsg, tr("Control socket is not connected."));
00242 }
00243 QCoreApplication::postEvent(_sock, new SendCommandEvent(cmd, _sendWaiter));
00244 _connMutex.unlock();
00245
00246 return _sendWaiter->getResult(errmsg);
00247 }
00248
00249
00250 void
00251 ControlConnection::onReadyRead()
00252 {
00253 QMutexLocker locker(&_connMutex);
00254 ReceiveWaiter *waiter;
00255 QString errmsg;
00256
00257 while (_sock->canReadLine()) {
00258 ControlReply reply;
00259 if (_sock->readReply(reply, &errmsg)) {
00260 if (reply.getStatus() == "650") {
00261
00262 tc::debug("Control Event: %1").arg(reply.toString());
00263
00264 if (_events) {
00265 _events->handleEvent(reply);
00266 }
00267 } else {
00268
00269 tc::debug("Control Reply: %1").arg(reply.toString());
00270
00271 _recvMutex.lock();
00272 if (!_recvQueue.isEmpty()) {
00273 waiter = _recvQueue.dequeue();
00274 waiter->setResult(true, reply);
00275 }
00276 _recvMutex.unlock();
00277 }
00278 } else {
00279 tc::error("Unable to read control reply: %1").arg(errmsg);
00280 }
00281 }
00282 }
00283
00284
00285
00286 void
00287 ControlConnection::run()
00288 {
00289
00290 _connMutex.lock();
00291 _sock = new ControlSocket();
00292 _connectTimer = new QTimer();
00293 _connectTimer->setSingleShot(true);
00294
00295 QObject::connect(_sock, SIGNAL(readyRead()), this, SLOT(onReadyRead()),
00296 Qt::DirectConnection);
00297 QObject::connect(_sock, SIGNAL(disconnected()), this, SLOT(onDisconnected()),
00298 Qt::DirectConnection);
00299 QObject::connect(_sock, SIGNAL(connected()), this, SLOT(onConnected()),
00300 Qt::DirectConnection);
00301 QObject::connect(_sock, SIGNAL(error(QAbstractSocket::SocketError)),
00302 this, SLOT(onError(QAbstractSocket::SocketError)),
00303 Qt::DirectConnection);
00304 QObject::connect(_connectTimer, SIGNAL(timeout()), this, SLOT(connect()),
00305 Qt::DirectConnection);
00306
00307 _connMutex.unlock();
00308
00309
00310 connect();
00311 tc::debug("Starting control connection event loop.");
00312 exec();
00313 tc::debug("Exited control connection event loop.");
00314
00315
00316 _connMutex.lock();
00317 _sock->disconnect(this);
00318 delete _sock;
00319 delete _connectTimer;
00320 _sock = 0;
00321 _connMutex.unlock();
00322
00323
00324 if (_sendWaiter->status() == SendCommandEvent::SendWaiter::Waiting)
00325 _sendWaiter->setResult(false, tr("Control socket is not connected."));
00326
00327 _recvMutex.lock();
00328 while (!_recvQueue.isEmpty()) {
00329 ReceiveWaiter *w = _recvQueue.dequeue();
00330 w->setResult(false, ControlReply(),
00331 tr("Control socket is not connected."));
00332 }
00333 _recvMutex.unlock();
00334 }
00335
00336
00337
00338
00339
00340
00341 bool
00342 ControlConnection::ReceiveWaiter::getResult(ControlReply *reply,
00343 QString *errmsg)
00344 {
00345 forever {
00346 _mutex.lock();
00347 if (_status == Waiting) {
00348 _waitCond.wait(&_mutex);
00349 _mutex.unlock();
00350 } else {
00351 _mutex.unlock();
00352 break;
00353 }
00354 }
00355 if (errmsg) {
00356 *errmsg = _errmsg;
00357 }
00358 *reply = _reply;
00359 return (_status == Success);
00360 }
00361
00362
00363 void
00364 ControlConnection::ReceiveWaiter::setResult(bool success,
00365 const ControlReply &reply,
00366 const QString &errmsg)
00367 {
00368 _mutex.lock();
00369 _status = (success ? Success : Failed);
00370 _reply = reply;
00371 _errmsg = errmsg;
00372 _mutex.unlock();
00373 _waitCond.wakeAll();
00374 }
00375