00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <QHostAddress>
00029 #include <config/torsettings.h>
00030 #include <util/net.h>
00031 #include <util/file.h>
00032 #include "torcontrol.h"
00033
00034
00035
00036 TorControl::TorControl()
00037 {
00038
00039
00040
00041
00042
00043 _torProcess = 0;
00044
00045
00046
00047 _controlConn = new ControlConnection(&_torEvents);
00048
00049
00050 QObject::connect(_controlConn, SIGNAL(connected()),
00051 this, SLOT(onConnected()));
00052 QObject::connect(_controlConn, SIGNAL(connectFailed(QString)),
00053 this, SLOT(onConnectFailed(QString)));
00054 QObject::connect(_controlConn, SIGNAL(disconnected()),
00055 this, SLOT(onDisconnected()));
00056
00057 #if defined(Q_OS_WIN32)
00058 _torService = new TorService(this);
00059 QObject::connect(_torService, SIGNAL(started()),
00060 this, SLOT(onStarted()), Qt::QueuedConnection);
00061 QObject::connect(_torService, SIGNAL(finished(int, QProcess::ExitStatus)),
00062 this, SLOT(onStopped(int, QProcess::ExitStatus)));
00063 QObject::connect(_torService, SIGNAL(startFailed(QString)),
00064 this, SLOT(onStartFailed(QString)),
00065 Qt::QueuedConnection);
00066 #endif
00067 }
00068
00069
00070 TorControl::~TorControl()
00071 {
00072
00073 if (isConnected()) {
00074 disconnect();
00075 }
00076
00077 if (isVidaliaRunningTor()) {
00078 stop();
00079 }
00080 delete _controlConn;
00081 }
00082
00083
00084
00085 void
00086 TorControl::start()
00087 {
00088 if (isRunning()) {
00089 emit started();
00090 } else {
00091 TorSettings settings;
00092
00093
00094
00095 QString torrc = settings.getTorrc();
00096 if (!torrc.isEmpty()) {
00097 touch_file(torrc, true);
00098 }
00099
00100 #if defined(Q_OS_WIN32)
00101 if (TorService::isSupported() && _torService->isInstalled()) {
00102 _torService->start();
00103
00104 } else {
00105 #endif
00106 _torProcess = new TorProcess;
00107
00108
00109 QObject::connect(_torProcess, SIGNAL(started()),
00110 this, SLOT(onStarted()), Qt::QueuedConnection);
00111 QObject::connect(_torProcess, SIGNAL(finished(int, QProcess::ExitStatus)),
00112 this, SLOT(onStopped(int, QProcess::ExitStatus)));
00113 QObject::connect(_torProcess, SIGNAL(startFailed(QString)),
00114 this, SLOT(onStartFailed(QString)), Qt::QueuedConnection);
00115 QObject::connect(_torProcess, SIGNAL(log(QString, QString)),
00116 this, SLOT(onLogStdout(QString, QString)));
00117
00118
00119 _torProcess->start(expand_filename(settings.getExecutable()),
00120 settings.getArguments());
00121 #if defined(Q_OS_WIN32)
00122 }
00123 #endif
00124 }
00125 }
00126
00127
00128 void
00129 TorControl::onStarted()
00130 {
00131 emit started();
00132 }
00133
00134
00135
00136 void
00137 TorControl::onStartFailed(QString errmsg)
00138 {
00139
00140 closeTorProcess();
00141
00142 emit startFailed(errmsg);
00143 }
00144
00145
00146 bool
00147 TorControl::stop(QString *errmsg)
00148 {
00149
00150 if (!isRunning()) {
00151 return true;
00152 }
00153
00154 if (!_torProcess) {
00155 return this->signal(TorSignal::Halt);
00156 } else {
00157
00158 return _torProcess->stop(errmsg);
00159 }
00160 }
00161
00162
00163 void
00164 TorControl::onStopped(int exitCode, QProcess::ExitStatus exitStatus)
00165 {
00166 closeTorProcess();
00167
00168 if (_controlConn->status() == ControlConnection::Connecting)
00169 _controlConn->cancelConnect();
00170
00171 emit stopped();
00172 emit stopped(exitCode, exitStatus);
00173 }
00174
00175
00176 void
00177 TorControl::closeTorProcess()
00178 {
00179 if (_torProcess) {
00180 QObject::disconnect(_torProcess, 0, 0, 0);
00181 delete _torProcess;
00182 _torProcess = 0;
00183 }
00184 }
00185
00186
00187
00188 bool
00189 TorControl::isVidaliaRunningTor()
00190 {
00191 if (_torProcess) {
00192 return (_torProcess->pid() != 0);
00193 }
00194 return false;
00195 }
00196
00197
00198 bool
00199 TorControl::isRunning()
00200 {
00201 if (_torProcess) {
00202 return (_torProcess->pid() != 0);
00203 }
00204
00205 TorSettings settings;
00206 if (net_test_connect(settings.getControlAddress(),
00207 settings.getControlPort(), 250)) {
00208 return true;
00209 }
00210 return false;
00211 }
00212
00213
00214 void
00215 TorControl::onLogStdout(QString severity, QString message)
00216 {
00217 LogEvent::Severity s = LogEvent::toSeverity(severity);
00218 _torEvents.dispatch(TorEvents::toTorEvent(s), new LogEvent(s, message));
00219 }
00220
00221
00222
00223 void
00224 TorControl::connect()
00225 {
00226 TorSettings settings;
00227 _controlConn->connect(settings.getControlAddress(),
00228 settings.getControlPort());
00229 }
00230
00231
00232
00233 void
00234 TorControl::onConnected()
00235 {
00236
00237 emit connected();
00238 }
00239
00240
00241 void
00242 TorControl::onConnectFailed(QString errmsg)
00243 {
00244 emit connectFailed(errmsg);
00245 }
00246
00247
00248 void
00249 TorControl::disconnect()
00250 {
00251 if (isConnected())
00252 _controlConn->disconnect();
00253 }
00254
00255
00256 void
00257 TorControl::onDisconnected()
00258 {
00259 if (_torProcess) {
00260
00261
00262
00263 _torProcess->openStdout();
00264 }
00265
00266 _torVersion = QString();
00267
00268
00269 emit disconnected();
00270 }
00271
00272
00273 bool
00274 TorControl::isConnected()
00275 {
00276 return (_controlConn->status() == ControlConnection::Connected);
00277 }
00278
00279
00280
00281
00282
00283 bool
00284 TorControl::send(ControlCommand cmd, ControlReply &reply, QString *errmsg)
00285 {
00286 if (_controlConn->send(cmd, reply, errmsg)) {
00287 if (reply.getStatus() == "250") {
00288 return true;
00289 }
00290 if (errmsg) {
00291 *errmsg = reply.getMessage();
00292 }
00293 }
00294 return false;
00295 }
00296
00297
00298 bool
00299 TorControl::send(ControlCommand cmd, QString *errmsg)
00300 {
00301 ControlReply reply;
00302 return send(cmd, reply, errmsg);
00303 }
00304
00305
00306
00307
00308
00309 bool
00310 TorControl::authenticate(const QByteArray cookie, QString *errmsg)
00311 {
00312 ControlCommand cmd("AUTHENTICATE", base16_encode(cookie));
00313 ControlReply reply;
00314 QString str;
00315
00316 if (!send(cmd, reply, &str)) {
00317 emit authenticationFailed(str);
00318 return err(errmsg, str);
00319 }
00320 onAuthenticated();
00321 return true;
00322 }
00323
00324
00325
00326
00327
00328 bool
00329 TorControl::authenticate(const QString password, QString *errmsg)
00330 {
00331 ControlCommand cmd("AUTHENTICATE", QString("%1")
00332 .arg(string_escape(password)));
00333 ControlReply reply;
00334 QString str;
00335
00336 if (!send(cmd, reply, &str)) {
00337 emit authenticationFailed(str);
00338 return err(errmsg, str);
00339 }
00340 onAuthenticated();
00341 return true;
00342 }
00343
00344
00345 void
00346 TorControl::onAuthenticated()
00347 {
00348
00349
00350 getInfo("version", _torVersion);
00351
00352
00353 if (_torProcess)
00354 _torProcess->closeStdout();
00355
00356 emit authenticated();
00357 }
00358
00359
00360 ProtocolInfo
00361 TorControl::protocolInfo(QString *errmsg)
00362 {
00363 ControlCommand cmd("PROTOCOLINFO", "1");
00364 ControlReply reply;
00365 ProtocolInfo pi;
00366 QString msg, topic;
00367 QHash<QString,QString> keyvals;
00368 int idx;
00369 bool ok;
00370
00371 if (!send(cmd, reply, errmsg))
00372 return ProtocolInfo();
00373
00374 foreach (ReplyLine line, reply.getLines()) {
00375 if (line.getStatus() != "250")
00376 continue;
00377
00378 msg = line.getMessage().trimmed();
00379 idx = msg.indexOf(" ");
00380 topic = msg.mid(0, idx).toUpper();
00381
00382 if (idx > 0) {
00383 keyvals = string_parse_keyvals(msg.mid(idx+1), &ok);
00384 if (!ok)
00385 continue;
00386 } else {
00387 keyvals = QHash<QString,QString>();
00388 }
00389
00390 if (topic == "AUTH") {
00391 if (keyvals.contains("METHODS"))
00392 pi.setAuthMethods(keyvals.value("METHODS"));
00393 if (keyvals.contains("COOKIEFILE"))
00394 pi.setCookieAuthFile(keyvals.value("COOKIEFILE"));
00395 } else if (topic == "VERSION") {
00396 if (keyvals.contains("Tor"))
00397 pi.setTorVersion(keyvals.value("Tor"));
00398 }
00399 }
00400 return pi;
00401 }
00402
00403
00404
00405
00406
00407
00408 bool
00409 TorControl::getInfo(QHash<QString,QString> &map, QString *errmsg)
00410 {
00411 ControlCommand cmd("GETINFO");
00412 ControlReply reply;
00413
00414
00415 foreach (QString key, map.keys()) {
00416 cmd.addArgument(key);
00417 }
00418
00419
00420 if (send(cmd, reply, errmsg)) {
00421
00422 foreach (ReplyLine line, reply.getLines()) {
00423
00424 QStringList keyval = line.getMessage().split("=");
00425 if (keyval.size() == 2) {
00426 map.insert(keyval.at(0), keyval.at(1));
00427 }
00428 }
00429 return true;
00430 }
00431 return false;
00432 }
00433
00434
00435 bool
00436 TorControl::getInfo(QString key, QString &val, QString *errmsg)
00437 {
00438 QHash<QString,QString> map;
00439 map.insert(key, "");
00440
00441 if (getInfo(map, errmsg)) {
00442 val = map.value(key);
00443 return true;
00444 }
00445 return false;
00446 }
00447
00448
00449 bool
00450 TorControl::signal(TorSignal::Signal sig, QString *errmsg)
00451 {
00452 ControlCommand cmd("SIGNAL");
00453 cmd.addArgument(TorSignal::toString(sig));
00454 if (sig == TorSignal::Shutdown || sig == TorSignal::Halt) {
00455 return _controlConn->send(cmd, errmsg);
00456 }
00457 return send(cmd, errmsg);
00458 }
00459
00460
00461
00462 QHostAddress
00463 TorControl::getSocksAddress(QString *errmsg)
00464 {
00465 QHostAddress socksAddr;
00466
00467
00468 if (getSocksPort() == 0) {
00469 return QHostAddress::Null;
00470 }
00471
00472
00473
00474 QStringList addrList = getSocksAddressList(errmsg);
00475 foreach (QString addr, addrList) {
00476 addr = addr.mid(0, addr.indexOf(":"));
00477 if (socksAddr.setAddress(addr)) {
00478 return socksAddr;
00479 }
00480 }
00481
00482 return QHostAddress::LocalHost;
00483 }
00484
00485
00486
00487 QStringList
00488 TorControl::getSocksAddressList(QString *errmsg)
00489 {
00490 QStringList addrList;
00491 if (getConf("SocksListenAddress", addrList, errmsg)) {
00492 return addrList;
00493 }
00494 return QStringList();
00495 }
00496
00497
00498
00499 quint16
00500 TorControl::getSocksPort(QString *errmsg)
00501 {
00502 QList<quint16> portList = getSocksPortList(errmsg);
00503 if (portList.size() > 0) {
00504 return portList.at(0);
00505 }
00506 return 0;
00507 }
00508
00509
00510
00511 QList<quint16>
00512 TorControl::getSocksPortList(QString *errmsg)
00513 {
00514 bool valid;
00515 quint16 port, socksPort;
00516 QString portString;
00517 QList<quint16> portList;
00518
00519
00520 if (getConf("SocksPort", portString, errmsg)) {
00521 socksPort = (quint16)portString.toUInt(&valid);
00522 if (valid) {
00523 if (socksPort == 0) {
00524
00525
00526 return QList<quint16>();
00527 }
00528 }
00529 }
00530
00531 QStringList addrList = getSocksAddressList(errmsg);
00532 foreach (QString addr, addrList) {
00533 if (addr.contains(":")) {
00534 portString = addr.mid(addr.indexOf(":")+1);
00535 port = (quint16)portString.toUInt(&valid);
00536 if (valid) {
00537 portList << port;
00538 }
00539 }
00540 }
00541
00542
00543 if (!portList.size() || (portList.size() != addrList.size())) {
00544 portList << socksPort;
00545 }
00546 return portList;
00547 }
00548
00549
00550 QString
00551 TorControl::getTorVersionString()
00552 {
00553 return _torVersion;
00554 }
00555
00556
00557
00558 quint32
00559 TorControl::getTorVersion()
00560 {
00561 static QString versionString;
00562 static quint32 version = 0;
00563 quint8 major, minor, micro, patch;
00564
00565
00566 if (versionString == _torVersion)
00567 return version;
00568 versionString = _torVersion;
00569
00570
00571 QStringList parts = versionString.split(QRegExp("\\.|-"));
00572 if (parts.size() >= 4) {
00573 major = (quint8)parts.at(0).toUInt();
00574 minor = (quint8)parts.at(1).toUInt();
00575 micro = (quint8)parts.at(2).toUInt();
00576 patch = (quint8)parts.at(3).toUInt();
00577 version = ((major << 24) | (minor << 16) | (micro << 8) | patch);
00578 } else {
00579
00580 version = 0;
00581 }
00582 return version;
00583 }
00584
00585
00586
00587
00588 bool
00589 TorControl::setEvent(TorEvents::TorEvent e, QObject *obj,
00590 bool add, bool set, QString *errmsg)
00591 {
00592 if (add) {
00593 _torEvents.add(e, obj);
00594 } else {
00595 _torEvents.remove(e, obj);
00596 }
00597 if (set && isConnected()) {
00598 return setEvents(errmsg);
00599 }
00600 return true;
00601 }
00602
00603
00604
00605
00606 bool
00607 TorControl::setLogEvents(uint filter, QObject *obj, QString *errmsg)
00608 {
00609 setEvent(TorEvents::LogError , obj, filter & LogEvent::Error , false);
00610 setEvent(TorEvents::LogWarn , obj, filter & LogEvent::Warn , false);
00611 setEvent(TorEvents::LogNotice, obj, filter & LogEvent::Notice, false);
00612 setEvent(TorEvents::LogInfo , obj, filter & LogEvent::Info , false);
00613 setEvent(TorEvents::LogDebug , obj, filter & LogEvent::Debug , false);
00614 return (isConnected() ? setEvents(errmsg) : true);
00615 }
00616
00617
00618 bool
00619 TorControl::setEvents(QString *errmsg)
00620 {
00621 ControlCommand cmd("SETEVENTS");
00622
00623
00624 foreach (TorEvents::TorEvent e, _torEvents.eventList()) {
00625 cmd.addArgument(TorEvents::toString(e));
00626 }
00627 return send(cmd, errmsg);
00628 }
00629
00630
00631
00632 bool
00633 TorControl::setConf(QHash<QString,QString> map, QString *errmsg)
00634 {
00635 ControlCommand cmd("SETCONF");
00636 QString arg, value;
00637
00638
00639 foreach (QString key, map.keys()) {
00640 arg = key;
00641 value = map.value(key);
00642 if (value.length() > 0) {
00643 arg += "=\"" + value + "\"";
00644 }
00645 cmd.addArgument(arg);
00646 }
00647 return send(cmd, errmsg);
00648 }
00649
00650
00651 bool
00652 TorControl::setConf(QString key, QString value, QString *errmsg)
00653 {
00654 QHash<QString,QString> map;
00655 map.insert(key, value);
00656 return setConf(map, errmsg);
00657 }
00658
00659
00660
00661 bool
00662 TorControl::getConf(QHash<QString,QString> &map, QString *errmsg)
00663 {
00664 QHash<QString,QStringList> multiMap;
00665 foreach (QString key, map.keys()) {
00666 multiMap.insert(key, QStringList());
00667 }
00668 if (getConf(multiMap, errmsg)) {
00669 foreach (QString key, multiMap.keys()) {
00670 if (map.contains(key)) {
00671 map.insert(key, multiMap.value(key).join("\n"));
00672 }
00673 }
00674 }
00675 return false;
00676 }
00677
00678
00679 bool
00680 TorControl::getConf(QHash<QString,QStringList> &map, QString *errmsg)
00681 {
00682 ControlCommand cmd("GETCONF");
00683 ControlReply reply;
00684 QStringList confValue;
00685 QString confKey;
00686
00687
00688 foreach (QString key, map.keys()) {
00689 cmd.addArgument(key);
00690 }
00691
00692
00693 if (send(cmd, reply, errmsg)) {
00694
00695 foreach (ReplyLine line, reply.getLines()) {
00696
00697 QStringList keyval = line.getMessage().split("=");
00698 if (keyval.size() == 2) {
00699 confKey = keyval.at(0);
00700
00701 if (map.contains(confKey)) {
00702
00703
00704 confValue = map.value(confKey);
00705 }
00706 confValue << keyval.at(1);
00707 map.insert(keyval.at(0), confValue);
00708 }
00709 }
00710 return true;
00711 }
00712 return false;
00713 }
00714
00715
00716 bool
00717 TorControl::getConf(QString key, QString &value, QString *errmsg)
00718 {
00719 QStringList confValues;
00720 if (getConf(key, confValues, errmsg)) {
00721 value = confValues.join("\n");
00722 return true;
00723 }
00724 return false;
00725 }
00726
00727
00728 bool
00729 TorControl::getConf(QString key, QStringList &value, QString *errmsg)
00730 {
00731 QHash<QString,QStringList> map;
00732 map.insert(key, QStringList());
00733
00734 if (getConf(map, errmsg)) {
00735 value = map.value(key);
00736 return true;
00737 }
00738 return false;
00739 }
00740
00741
00742 bool
00743 TorControl::saveConf(QString *errmsg)
00744 {
00745 ControlCommand cmd("SAVECONF");
00746 return send(cmd, errmsg);
00747 }
00748
00749
00750 bool
00751 TorControl::resetConf(QStringList keys, QString *errmsg)
00752 {
00753 ControlCommand cmd("RESETCONF");
00754
00755
00756 foreach (QString key, keys) {
00757 cmd.addArgument(key);
00758 }
00759 return send(cmd, errmsg);
00760 }
00761
00762
00763
00764 bool
00765 TorControl::resetConf(QString key, QString *errmsg)
00766 {
00767 return resetConf(QStringList() << key, errmsg);
00768 }
00769
00770
00771 RouterDescriptor
00772 TorControl::getDescriptorByName(QString name, QString *errmsg)
00773 {
00774 QList<RouterDescriptor> rdlist;
00775 RouterDescriptor rd;
00776
00777 rdlist = getDescriptorListByName(QStringList() << name, errmsg);
00778 if (!rdlist.isEmpty()) {
00779 rd = (RouterDescriptor)rdlist.takeFirst();
00780 return rd;
00781 }
00782 return RouterDescriptor();
00783 }
00784
00785
00786 RouterDescriptor
00787 TorControl::getDescriptorById(QString id, QString *errmsg)
00788 {
00789 QList<RouterDescriptor> rdlist;
00790 RouterDescriptor rd;
00791
00792 rdlist = getDescriptorListById(QStringList() << id, errmsg);
00793 if (!rdlist.isEmpty()) {
00794 rd = (RouterDescriptor)rdlist.takeFirst();
00795 return rd;
00796 }
00797 return RouterDescriptor();
00798 }
00799
00800
00801 QList<RouterDescriptor>
00802 TorControl::getDescriptorListByName(QStringList nameList, QString *errmsg)
00803 {
00804 ControlCommand cmd("GETINFO");
00805 ControlReply reply;
00806 QList<RouterDescriptor> rdlist;
00807
00808
00809 if (nameList.isEmpty()) {
00810 return QList<RouterDescriptor>();
00811 }
00812
00813
00814 foreach (QString name, nameList) {
00815 cmd.addArgument("desc/name/"+ name);
00816 }
00817
00818
00819 if (send(cmd, reply, errmsg)) {
00820 foreach (ReplyLine line, reply.getLines()) {
00821
00822 if (line.getStatus() == "250" && !line.getData().isEmpty()) {
00823
00824 rdlist << RouterDescriptor(line.getData());
00825 }
00826 }
00827 }
00828 return rdlist;
00829 }
00830
00831
00832 QList<RouterDescriptor>
00833 TorControl::getDescriptorListById(QStringList idlist, QString *errmsg)
00834 {
00835 ControlCommand cmd("GETINFO");
00836 ControlReply reply;
00837 QHash<QString,bool> offline;
00838 QList<RouterDescriptor> rdlist;
00839
00840
00841 if (idlist.isEmpty()) {
00842 return QList<RouterDescriptor>();
00843 }
00844
00845
00846 foreach (QString id, idlist) {
00847 if (id.startsWith("!")) {
00848
00849
00850 id = id.remove("!");
00851 offline.insert(id, true);
00852 }
00853 cmd.addArgument("desc/id/"+ id);
00854 }
00855
00856
00857 if (send(cmd, reply, errmsg)) {
00858 foreach (ReplyLine line, reply.getLines()) {
00859
00860 if (line.getStatus() == "250" && !line.getData().isEmpty()) {
00861
00862 RouterDescriptor rd(line.getData());
00863 rd.setOffline(!offline.isEmpty() && offline.contains(rd.id()));
00864 rdlist << rd;
00865 }
00866 }
00867 }
00868 return rdlist;
00869 }
00870
00871
00872
00873 QList<RouterDescriptor>
00874 TorControl::getRouterList(QString *errmsg)
00875 {
00876
00877 QStringList idList = getRouterIDList(errmsg);
00878
00879 return getDescriptorListById(idList, errmsg);
00880 }
00881
00882
00883 QStringList
00884 TorControl::getRouterIDList(QString *errmsg)
00885 {
00886 ControlCommand cmd("GETINFO", "network-status");
00887 ControlReply reply;
00888 QStringList idList;
00889
00890 if (send(cmd, reply, errmsg)) {
00891 QString routerIDs = reply.getMessage().remove(0,qstrlen("network-status="));
00892
00893
00894 QStringList routers = routerIDs.split(" ");
00895 foreach (QString router, routers) {
00896
00897 QString id = router.mid(router.indexOf("=")+1);
00898 id = id.replace("$", "");
00899
00900 if (router.startsWith("!") && !id.startsWith("!")) {
00901 id.prepend("!");
00902 }
00903
00904 idList << id;
00905 }
00906 }
00907 return idList;
00908 }
00909
00910
00911 QList<Circuit>
00912 TorControl::getCircuits(QString *errmsg)
00913 {
00914 ControlCommand cmd("GETINFO", "circuit-status");
00915 ControlReply reply;
00916 QList<Circuit> circuits;
00917 Circuit c;
00918
00919 if (send(cmd, reply, errmsg)) {
00920
00921 QString msg = reply.getMessage();
00922 c = Circuit::fromString(msg.mid(msg.indexOf("=")+1));
00923 if (!c.isEmpty()) {
00924 circuits << c;
00925 }
00926
00927
00928 foreach(QString line, reply.getData()) {
00929 c = Circuit::fromString(line);
00930 if (!c.isEmpty()) {
00931 circuits << Circuit::fromString(line);
00932 }
00933 }
00934 }
00935 return circuits;
00936 }
00937
00938
00939
00940 bool
00941 TorControl::closeCircuit(quint64 circid, bool ifUnused, QString *errmsg)
00942 {
00943 ControlCommand cmd("CLOSECIRCUIT", QString::number(circid));
00944 if (ifUnused) {
00945 cmd.addArgument("IfUnused");
00946 }
00947 return send(cmd, errmsg);
00948 }
00949
00950
00951 QList<Stream>
00952 TorControl::getStreams(QString *errmsg)
00953 {
00954 ControlCommand cmd("GETINFO", "stream-status");
00955 ControlReply reply;
00956 QList<Stream> streams;
00957 Stream s;
00958
00959 if (send(cmd, reply, errmsg)) {
00960
00961 QString msg = reply.getMessage();
00962 s = Stream::fromString(msg.mid(msg.indexOf("=")+1));
00963 if (!s.isEmpty()) {
00964 streams << s;
00965 }
00966
00967
00968 foreach (QString line, reply.getData()) {
00969 s = Stream::fromString(line);
00970 if (!s.isEmpty()) {
00971 streams << s;
00972 }
00973 }
00974 }
00975 return streams;
00976 }
00977
00978
00979 bool
00980 TorControl::closeStream(quint64 streamid, QString *errmsg)
00981 {
00982 ControlCommand cmd("CLOSESTREAM", QString::number(streamid));
00983 cmd.addArgument("1");
00984 return send(cmd, errmsg);
00985 }
00986
00987
00988
00989 AddressMap
00990 TorControl::getAddressMap(AddressMap::AddressMapType type, QString *errmsg)
00991 {
00992 ControlCommand cmd("GETINFO");
00993 ControlReply reply;
00994 AddressMap addressMap;
00995
00996 switch (type) {
00997 case AddressMap::AddressMapConfig:
00998 cmd.addArgument("addr-mappings/config");
00999 break;
01000 case AddressMap::AddressMapCache:
01001 cmd.addArgument("addr-mappings/cache");
01002 break;
01003 case AddressMap::AddressMapControl:
01004 cmd.addArgument("addr-mappings/control");
01005 break;
01006 default:
01007 cmd.addArgument("addr-mappings/all");
01008 }
01009
01010 if (send(cmd, reply, errmsg)) {
01011 foreach (QString mapping, reply.getData()) {
01012 addressMap.add(mapping);
01013 }
01014 }
01015 return addressMap;
01016 }
01017