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