Vidalia 0.2.10
|
00001 /* 00002 ** This file is part of Vidalia, and is subject to the license terms in the 00003 ** LICENSE file, found in the top level directory of this distribution. If 00004 ** you did not receive the LICENSE file with this file, you may obtain it 00005 ** from the Vidalia source package distributed by the Vidalia Project at 00006 ** http://www.vidalia-project.net/. No part of Vidalia, including this file, 00007 ** may be copied, modified, propagated, or distributed except according to 00008 ** the terms described in the LICENSE file. 00009 */ 00010 00011 /* 00012 ** \file ControlConnection.cpp 00013 ** \version $Id: ControlConnection.cpp 3735 2009-04-28 20:28:01Z edmanm $ 00014 ** \brief A connection to Tor's control interface, responsible for sending and 00015 ** receiving commands and events 00016 */ 00017 00018 #include "ControlConnection.h" 00019 #include "tcglobal.h" 00020 #include "stringutil.h" 00021 00022 #include <QCoreApplication> 00023 #include <QMutexLocker> 00024 00025 /** Maximum number of times we'll try to connect to Tor before giving up.*/ 00026 #define MAX_CONNECT_ATTEMPTS 5 00027 /** Time to wait between control connection attempts (in milliseconds). */ 00028 #define CONNECT_RETRY_DELAY 2*1000 00029 00030 00031 /** Default constructor. */ 00032 ControlConnection::ControlConnection(TorEvents *events) 00033 { 00034 _events = events; 00035 _status = Unset; 00036 _sock = 0; 00037 _sendWaiter = new SendCommandEvent::SendWaiter(); 00038 } 00039 00040 /** Destructor. */ 00041 ControlConnection::~ControlConnection() 00042 { 00043 /* Exit the event loop */ 00044 exit(); 00045 /* Wait for the thread to finish */ 00046 wait(); 00047 /* Clean up after the send waiter */ 00048 delete _sendWaiter; 00049 } 00050 00051 /** Connect to the specified Tor control interface. */ 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 /* Save the destination information */ 00062 _addr = addr; 00063 _port = port; 00064 _sock = 0; 00065 _connectAttempt = 0; 00066 setStatus(Connecting); 00067 00068 /* Kick off the thread in which the control socket will live */ 00069 QThread::start(); 00070 } 00071 00072 /** Attempt to establish a connection to Tor's control interface. We will try 00073 * a maximum of MAX_CONNECT_ATTEMPTS, waiting CONNECT_RETRY_DELAY between each 00074 * attempt, to give slow Tors a chance to finish binding their control port. */ 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 /** Disconnect from Tor's control interface. */ 00088 void 00089 ControlConnection::disconnect() 00090 { 00091 setStatus(Disconnecting); 00092 _connMutex.lock(); 00093 _sock->disconnectFromHost(); 00094 _connMutex.unlock(); 00095 } 00096 00097 /** Called when the control socket is connected. This method checks that the 00098 * control protocol version of the Tor we connected to is at least V1. */ 00099 void 00100 ControlConnection::onConnected() 00101 { 00102 setStatus(Connected); 00103 emit connected(); 00104 } 00105 00106 /** Called when the control socket is disconnected and stops the control 00107 * thread's event loop. */ 00108 void 00109 ControlConnection::onDisconnected() 00110 { 00111 setStatus(Disconnected); 00112 emit disconnected(); 00113 exit(0); 00114 } 00115 00116 /** Called when the control socket encounters <b>error</b>. */ 00117 void 00118 ControlConnection::onError(QAbstractSocket::SocketError error) 00119 { 00120 if (status() == Connecting) { 00121 /* If we got a 'connection refused' and we haven't exceeded 00122 * MAX_CONNECT_ATTEMPTS, then try to reconnect since Tor is probably 00123 * running, but it doesn't have a ControlPort open yet. */ 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 /* Exceeded maximum number of connect attempts. Give up. */ 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 /* Tor closed the connection. This is common when we send a 'shutdown' or 00139 * 'halt' signal to Tor and doesn't need to be logged as loudly. */ 00140 tc::warn("Tor closed the control connection."); 00141 } else { 00142 /* Some other error. */ 00143 /*XXX We may want to be emitting these so the GUI thread can learn about 00144 * them and display an error message. */ 00145 tc::error("Control socket error: %1").arg(ControlSocket::toString(error)); 00146 } 00147 } 00148 00149 /** Cancels a pending control connection to Tor. */ 00150 void 00151 ControlConnection::cancelConnect() 00152 { 00153 tc::warn("Control connection attempt cancelled."); 00154 setStatus(Disconnected); 00155 exit(0); 00156 } 00157 00158 /** Returns true if the control socket is connected to Tor. */ 00159 bool 00160 ControlConnection::isConnected() 00161 { 00162 return (status() == Connected); 00163 } 00164 00165 /** Returns the status of the control connection. */ 00166 ControlConnection::Status 00167 ControlConnection::status() 00168 { 00169 QMutexLocker locker(&_statusMutex); 00170 return _status; 00171 } 00172 00173 /** Returns a string description of the control Status value 00174 * <b>status</b>. */ 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 /** Sets the control connection status. */ 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 /** Sends a control command to Tor and waits for the reply. */ 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 /* Create and enqueue a new receive waiter */ 00212 ReceiveWaiter *w = new ReceiveWaiter(); 00213 _recvQueue.enqueue(w); 00214 _recvMutex.unlock(); 00215 00216 /* Wait for and get the result, clean up, and return */ 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 /** Sends a control command to Tor and returns true if the command was sent 00233 * successfully. Otherwise, returns false and <b>*errmsg</b> (if supplied) 00234 * will be set. */ 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 /** Called when there is data on the control socket. */ 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 /* Asynchronous event message */ 00262 tc::debug("Control Event: %1").arg(reply.toString()); 00263 00264 if (_events) { 00265 _events->handleEvent(reply); 00266 } 00267 } else { 00268 /* Response to a previous command */ 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 /** Main thread implementation. Creates and connects a control socket, then 00285 * spins up an event loop. */ 00286 void 00287 ControlConnection::run() 00288 { 00289 /* Create a new control socket */ 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 /* Attempt to connect to Tor */ 00310 connect(); 00311 tc::debug("Starting control connection event loop."); 00312 exec(); 00313 tc::debug("Exited control connection event loop."); 00314 00315 /* Clean up the socket */ 00316 _connMutex.lock(); 00317 _sock->disconnect(this); 00318 delete _sock; 00319 delete _connectTimer; 00320 _sock = 0; 00321 _connMutex.unlock(); 00322 00323 /* If there are any messages waiting for a response, clear them. */ 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 * ControlConnection::ReceiveWaiter 00339 */ 00340 /** Waits for and gets the reply from a control command. */ 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 /** Sets the result and reply from a control command. */ 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