Changeset 90

Show
Ignore:
Timestamp:
01/15/06 17:36:23 (3 years ago)
Author:
edmanm
Message:

Check in a bulk of the asynchronous event handling code. Some work remains.

Location:
trunk/src
Files:
4 added
6 modified

Legend:

Unmodified
Added
Removed
  • trunk/src/control/control.pri

    r59 r90  
    2727           $$PWD/controlcommand.h \ 
    2828           $$PWD/controlreply.h \ 
    29            $$PWD/replyline.h 
     29           $$PWD/replyline.h \ 
     30           $$PWD/torevents.h \ 
     31           $$PWD/messagepump.h 
    3032 
    3133SOURCES += $$PWD/torcontrol.cpp \ 
     
    3436           $$PWD/controlcommand.cpp \ 
    3537           $$PWD/controlreply.cpp \ 
    36            $$PWD/replyline.cpp 
     38           $$PWD/replyline.cpp \ 
     39           $$PWD/torevents.cpp \ 
     40           $$PWD/messagepump.cpp 
  • trunk/src/control/controlreply.cpp

    r59 r90  
    5454} 
    5555 
     56/** Returns the status of the first line in the reply */ 
     57QString 
     58ControlReply::getStatus() 
     59{ 
     60  return getLine().getStatus(); 
     61} 
     62 
  • trunk/src/control/controlreply.h

    r59 r90  
    4646  /** Returns all lines for this reply */ 
    4747  QList<ReplyLine> getLines(); 
     48 
     49  /** Returns the status of the first line in the reply */ 
     50  QString getStatus(); 
    4851   
    4952private: 
  • trunk/src/control/torcontrol.cpp

    r84 r90  
    2121 *  Boston, MA  02110-1301, USA. 
    2222 ****************************************************************/ 
    23                       
     23                    
    2424#include <QHostAddress> 
    2525 
     
    3030TorControl::TorControl() 
    3131{ 
     32  /* Construct the message pump and give it a control connection and TorEvents 
     33   * object, used to translate and dispatch event messages sent by Tor */ 
     34  _messages = new MessagePump(&_controlConn, &_events); 
     35 
     36  /* Plumb the signal relays between the TorEvents object and The Outside */ 
     37  QObject::connect(&_events, SIGNAL(bandwidth(quint64, quint64)), 
     38                   this, SLOT(onBandwidthUpdate(quint64, quit64)), 
     39                   Qt::DirectConnection); 
     40  QObject::connect(&_events, SIGNAL(log(TorEvents::LogSeverity, QString)), 
     41                   this, SLOT(onLogMessage(TorEvents::LogSeverity, QString)), 
     42                   Qt::DirectConnection); 
     43  QObject::connect(&_events, SIGNAL(circuit(quint64, TorEvents::CircuitStatus, 
     44                                            QString)), 
     45                   this, SLOT(onCircuitStatus(quint64, TorEvents::CircuitStatus, 
     46                                              QString)), 
     47                   Qt::DirectConnection); 
     48  QObject::connect(&_events, SIGNAL(stream(quint64, TorEvents::StreamStatus, 
     49                                           quint64, QString)), 
     50                   this, SLOT(onStreamStatus(quint64, TorEvents::StreamStatus, 
     51                                             quint64, QString)), 
     52                   Qt::DirectConnection); 
     53   
    3254  /* Plumb the process signals */ 
    3355  QObject::connect(&_torProcess, SIGNAL(started()), 
     
    4668TorControl::~TorControl() 
    4769{ 
     70  if (isConnected()) { 
     71    disconnect(); 
     72  } 
     73  if (isRunning()) { 
     74    stop(); 
     75  } 
     76  if (_messages) { 
     77    delete _messages; 
     78  } 
    4879} 
    4980 
     
    69100TorControl::stop(QString *errmsg) 
    70101{ 
     102  if (isConnected()) { 
     103    disconnect(); 
     104  } 
    71105  return _torProcess.stop(errmsg); 
    72106} 
     
    92126{ 
    93127  VidaliaSettings settings; 
    94   return _controlConn.connect(settings.getControlAddress(), 
    95                               settings.getControlPort(), errmsg); 
     128  if ( _controlConn.connect(settings.getControlAddress(), 
     129                            settings.getControlPort(), errmsg) 
     130     ) { 
     131    _messages->start(); 
     132    return true; 
     133  } 
     134  return false; 
    96135} 
    97136 
     
    108147TorControl::disconnect() 
    109148{ 
     149  _messages->stop(); 
     150  send(ControlCommand("QUIT"), 0); 
    110151  _controlConn.disconnect(); 
    111152} 
     
    123164{ 
    124165  return _controlConn.isValid(); 
     166} 
     167 
     168/** Sends a message to Tor and discards the response */ 
     169bool 
     170TorControl::send(ControlCommand cmd, QString *errmsg) 
     171{ 
     172  ControlReply reply; 
     173  return send(cmd, reply, errmsg); 
     174} 
     175 
     176/** Send a message to Tor and read the response */ 
     177bool 
     178TorControl::send(ControlCommand cmd, ControlReply &reply, QString *errmsg) 
     179{ 
     180  return _messages->send(cmd, reply, errmsg); 
    125181} 
    126182 
     
    137193  ControlReply reply; 
    138194 
    139   if (_controlConn.send(cmd, reply, errmsg)) { 
     195  if (send(cmd, reply, errmsg)) { 
    140196    ReplyLine line = reply.getLine(); 
    141197    if (line.getStatus() != "250") { 
     
    166222  
    167223  /* Ask Tor for the specified info values */ 
    168   if (_controlConn.send(cmd, reply, errmsg)) { 
     224  if (send(cmd, reply, errmsg)) { 
    169225   
    170226    /* Parse the response for the returned values */ 
     
    214270  /* Convert the signal to the correct string */ 
    215271  switch (sig) { 
    216     case Reload:   sigtype = "RELOAD"; break; 
    217     case Shutdown: sigtype = "SHUTDOWN"; break; 
    218     case Dump:     sigtype = "DUMP"; break; 
    219     case Debug:    sigtype = "DEBUG"; break; 
    220     case Halt:     sigtype = "HALT"; break; 
    221     default: return false; break; 
     272    case SignalReload:   sigtype = "RELOAD"; break; 
     273    case SignalShutdown: sigtype = "SHUTDOWN"; break; 
     274    case SignalDump:     sigtype = "DUMP"; break; 
     275    case SignalDebug:    sigtype = "DEBUG"; break; 
     276    case SignalHalt:     sigtype = "HALT"; break; 
     277    default: return false; 
    222278  } 
    223279   
    224280  /* Send and check the response */ 
    225   if (_controlConn.send(cmd, reply, errmsg)) { 
     281  if (!send(cmd, reply, errmsg)) { 
     282    return false; 
     283  } else { 
    226284    ReplyLine line = reply.getLine(); 
    227285    if (line.getStatus() != "250") { 
     
    246304} 
    247305 
     306/** Adds an event to the event list and registers it with Tor. If registration 
     307 * fails, then the event is NOT added to the event list. */ 
     308bool 
     309TorControl::addEvent(TorEvents::Event e, QString *errmsg) 
     310{ 
     311  QString event = TorEvents::toString(e); 
     312  _eventList << event; 
     313  if (!registerEvents(errmsg)) { 
     314    /* Registering the event failed, so remove it from the list */ 
     315    _eventList.removeAt(_eventList.indexOf(event)); 
     316    return false; 
     317  } 
     318  return true; 
     319} 
     320 
     321/** Removes an event from the event list and unregisters it from Tor. If 
     322 * unregistration fails, then the event is NOT removed from the event list. */ 
     323bool 
     324TorControl::removeEvent(TorEvents::Event e, QString *errmsg) 
     325{ 
     326  QString event = TorEvents::toString(e); 
     327  if (_eventList.contains(event)) { 
     328    _eventList.removeAt(_eventList.indexOf(event)); 
     329    if (!registerEvents(errmsg)) { 
     330      /* Unregistration failed, so leave it in the list */ 
     331      _eventList << event; 
     332      return false; 
     333    } 
     334  } 
     335  return true; 
     336} 
     337 
     338/** Register for the events currently in the event list */ 
     339bool 
     340TorControl::registerEvents(QString *errmsg) 
     341{ 
     342  ControlCommand cmd("SETEVENTS", _eventList.join(" "));  
     343  ControlReply reply; 
     344  if (!send(cmd, reply, errmsg)) { 
     345    return false; 
     346  } else { 
     347    ReplyLine line = reply.getLine(); 
     348    if (line.getStatus() != "250") { 
     349      if (errmsg) { 
     350        *errmsg = line.getMessage(); 
     351      } 
     352      return false; 
     353    } 
     354  } 
     355  return true; 
     356} 
     357 
     358/** 
     359 * The methods below relay the appropriate signals from the TorEvents object. 
     360 */ 
     361void 
     362TorControl::onBandwidthUpdate(quint64 bytesIn, quint64 bytesOut) 
     363{ 
     364  emit bandwidth(bytesIn, bytesOut); 
     365} 
     366void 
     367TorControl::onLogMessage(TorEvents::LogSeverity severity, QString msg) 
     368{ 
     369  emit log(severity, msg); 
     370} 
     371void 
     372TorControl::onCircuitStatus(quint64 circId,  
     373                            TorEvents::CircuitStatus status, QString path) 
     374{ 
     375  emit circuit(circId, status, path); 
     376} 
     377void 
     378TorControl::onStreamStatus(quint64 streamId, TorEvents::StreamStatus status, 
     379                           quint64 circId, QString target) 
     380{ 
     381  emit stream(streamId, status, circId, target); 
     382} 
     383 
  • trunk/src/control/torcontrol.h

    r84 r90  
    3030#include "controlconnection.h" 
    3131#include "torprocess.h" 
     32#include "messagepump.h" 
     33#include "torevents.h" 
     34 
    3235 
    3336class TorControl : public QObject 
     
    3841  /** Signals that can be sent by the controller */ 
    3942  enum Signal { 
    40     Reload, 
    41     Shutdown, 
    42     Dump, 
    43     Debug, 
    44     Halt 
     43    SignalReload, SignalShutdown, SignalDump, SignalDebug, SignalHalt 
    4544  }; 
    46    
     45  
     46 
    4747  /** Default constructor */ 
    4848  TorControl(); 
    49    
    5049  /** Default destructor */ 
    5150  ~TorControl(); 
     
    5352  /** Start the Tor process */ 
    5453  bool start(QString *errmsg = 0); 
    55  
    5654  /** Stop the Tor process */ 
    5755  bool stop(QString *errmsg = 0); 
    58  
    5956  /** Detect if the Tor process is running */ 
    6057  bool isRunning(); 
     
    6259  /** Connect to Tor's control socket */ 
    6360  bool connect(QString *errmsg = 0); 
    64  
    6561  /** Disconnect from Tor's control socket */ 
    6662  void disconnect(); 
    67  
    6863  /** Check if we're connected to Tor's control socket */ 
    6964  bool isConnected(); 
     
    7469  /** Sends a GETINFO message to Tor based on the given keys */ 
    7570  bool getInfo(QHash<QString,QString> &map, QString *errmsg = 0); 
    76  
    7771  /** Sends a GETINFO message for a single info value to Tor */ 
    7872  bool getInfo(QString key, QString &val, QString *errmsg = 0); 
     
    8478  QString getTorVersion(QString *errmsg = 0); 
    8579 
     80  /** Register another event of interest with Tor */ 
     81  bool addEvent(TorEvents::Event e, QString *errmsg = 0); 
     82  /** Remove a previously registered event */ 
     83  bool removeEvent(TorEvents::Event e, QString *errmsg = 0); 
     84 
    8685 
    8786signals: 
    8887  /** Emitted when the Tor process has started */ 
    8988  void started(); 
    90    
    9189  /** Emitted when the Tor process has stopped */ 
    9290  void stopped(int exitCode, QProcess::ExitStatus exitStatus); 
    93  
    9491  /** Emitted when the controller has connected to Tor */ 
    9592  void connected(); 
    96  
    9793  /** Emitted when the controller has disconnected from Tor */ 
    9894  void disconnected(); 
     95  /** Emitted when a bandwidth update is received from Tor */ 
     96  void bandwidth(quint64 bytesIn, quint64 bytesOut); 
     97  /** Emitted when a log message is received from Tor */ 
     98  void log(TorEvents::LogSeverity severity, QString msg); 
     99  /** Emitted when a circuit status event is received from Tor */ 
     100  void circuit(quint64 circId, TorEvents::CircuitStatus status, QString path); 
     101  /** Emitted when a stream status event is received from Tor */ 
     102  void stream(quint64 streamId, TorEvents::StreamStatus status, 
     103              quint64 circId, QString target); 
    99104 
    100  
     105   
    101106private: 
    102107  /** Instantiates a socket used to connect to Tor's control port */ 
     
    104109  /** Manages and monitors the Tor process */ 
    105110  TorProcess _torProcess;   
     111  /** Handles sending and receiving messages from Tor over the control 
     112   * connection */ 
     113  MessagePump *_messages; 
     114  /** Dispatches asynchronous events sent by Tor */ 
     115  TorEvents _events; 
     116  /** Keep track of which events we're interested in */ 
     117  QStringList _eventList; 
    106118 
     119  /** Register events of interest with Tor */ 
     120  bool registerEvents(QString *errmsg); 
     121  /** Sends a message to Tor and discards the response */ 
     122  bool send(ControlCommand cmd, QString *errmsg = 0); 
     123  /** Send a message to Tor and read the response */ 
     124  bool send(ControlCommand cmd, ControlReply &reply, QString *errmsg = 0); 
     125   
     126   
    107127/* The slots below simply relay signals from the appropriate member objects */ 
    108128private slots: 
     
    111131  void onConnected(); 
    112132  void onDisconnected(); 
     133  void onBandwidthUpdate(quint64 bytesIn, quint64 bytesOut); 
     134  void onLogMessage(TorEvents::LogSeverity severity, QString msg); 
     135  void onCircuitStatus(quint64 circId,  
     136                       TorEvents::CircuitStatus status, QString path); 
     137  void onStreamStatus(quint64 streamId, TorEvents::StreamStatus status, 
     138                      quint64 circId, QString target); 
    113139}; 
    114140 
  • trunk/src/gui/mainwindow.cpp

    r89 r90  
    149149  if (!_torControl->start(&errmsg)) { 
    150150    QMessageBox::warning(this, tr("Error Starting Tor"), 
    151        tr("Vidalia was unable to start Tor.\r\n\r\nError: ") + errmsg, 
     151       tr("Vidalia was unable to start Tor.\n\nError: ") + errmsg, 
    152152       QMessageBox::Ok, QMessageBox::NoButton); 
    153153  } 
     
    192192           "\n\nError: ") + errmsg, 
    193193        QMessageBox::Ok, QMessageBox::NoButton); 
     194    } else { 
     195      if (!_torControl->addEvent(TorEvents::Bandwidth, &errmsg)) { 
     196      QMessageBox::warning(this, tr("Authentication Error"), 
     197        tr("Vidalia was unable to authenticate itself to Tor." 
     198           "Check your authentication information and try again." 
     199           "\n\nError: ") + errmsg, 
     200        QMessageBox::Ok, QMessageBox::NoButton); 
     201      } 
    194202    } 
    195203  } 
     
    238246    if (!_isIntentionalExit) { 
    239247      QMessageBox::warning(this, tr("Tor Crashed"), 
    240         tr("Vidalia detected that the Tor process crashed.\n" 
     248        tr("Vidalia detected that the Tor process crashed.\n\n" 
    241249            "Please check the message log."), 
    242250         QMessageBox::Ok, QMessageBox::NoButton); 
     
    247255     * if this turns out to not be the case. */ 
    248256    QMessageBox::warning(this, tr("Tor Exited"), 
    249        tr("Tor exited and returned a non-zero exit code.\n" 
     257       tr("Tor exited and returned a non-zero exit code.\n\n" 
    250258          "Please check the message log."), 
    251259       QMessageBox::Ok, QMessageBox::NoButton);