
commit dd10e9d90d1a6e6b0099f49b6a1b46cc7209ec61 Author: Tomás Touceda <chiiph@torproject.org> Date: Mon Feb 13 12:37:47 2012 -0300 Add support for MicroDescriptors --- src/torcontrol/RouterDescriptor.cpp | 95 ++++++++++++++++++++++------------ src/torcontrol/RouterDescriptor.h | 27 ++++++++-- src/torcontrol/TorControl.cpp | 19 +++++++- src/torcontrol/TorControl.h | 2 + 4 files changed, 104 insertions(+), 39 deletions(-) diff --git a/src/torcontrol/RouterDescriptor.cpp b/src/torcontrol/RouterDescriptor.cpp index e63ca20..3634f3e 100644 --- a/src/torcontrol/RouterDescriptor.cpp +++ b/src/torcontrol/RouterDescriptor.cpp @@ -21,8 +21,8 @@ /** Constructor. Just assigns the ID and determines whether the router is * responsive or not based on the presence of a "!" at the start of the ID. * See tor-spec.txt for details. */ -RouterDescriptor::RouterDescriptor(QStringList descriptor) -{ +RouterDescriptor::RouterDescriptor(QStringList descriptor, bool microdesc) + : _microdesc(microdesc), _observedBandwidth(0), _uptime(0) { _status = Online; parseDescriptor(descriptor); } @@ -31,38 +31,56 @@ RouterDescriptor::RouterDescriptor(QStringList descriptor) void RouterDescriptor::parseDescriptor(QStringList descriptor) { - foreach (QString line, descriptor) { - if (line.startsWith("router ")) { - QStringList parts = line.remove(0,qstrlen("router ")).split(" "); - _name = parts.at(0); - _ip = QHostAddress(parts.at(1)); - _orPort = (quint16)parts.at(2).toUInt(); - _dirPort = (quint16)parts.at(4).toUInt(); - } else if (line.startsWith("platform ")) { - _platform = line.remove(0,qstrlen("platform ")); - } else if (line.startsWith("published ")) { - _published = QDateTime::fromString( - line.remove(0,qstrlen("published ")), - "yyyy-MM-dd HH:mm:ss"); - _published.setTimeSpec(Qt::UTC); - } else if (line.startsWith("opt fingerprint ")) { - _fingerprint = line.remove(0,qstrlen("opt fingerprint ")); - _id = _fingerprint.remove(" "); - } else if (line.startsWith("fingerprint ")) { - _fingerprint = line.remove(0,qstrlen("fingerprint ")); - _id = _fingerprint.remove(" "); - } else if (line.startsWith("uptime ")) { - _uptime = (quint64)line.remove(0,qstrlen("uptime ")).toULongLong(); - } else if (line.startsWith("bandwidth ")) { - QStringList bw = line.remove(0,qstrlen("bandwidth ")).split(" "); - _avgBandwidth = (quint64)bw.at(0).toULongLong(); - _burstBandwidth = (quint64)bw.at(1).toULongLong(); - _observedBandwidth = (quint64)bw.at(2).toULongLong(); - } else if (line.startsWith("contact ")) { - _contact = line.remove(0,qstrlen("contact ")); - } else if (line.startsWith("hibernating ")) { - if (line.remove(0,qstrlen("hibernating ")).trimmed() == "1") { - _status = Hibernating; + if(_microdesc) { + bool key = false; + foreach(QString line, descriptor) { + if(line.startsWith("onion-key")) { + key = true; + } else if(line.startsWith("p ")) { + _exitPolicy = line.remove(0,qstrlen("p ")); + } else if(line.startsWith("family ")) { + _family = line.remove(0,qstrlen("family ")); + } + + if(key) + _onionKey += line; + if(line.startsWith("-----END RSA PUBLIC KEY-----")) + key = false; + } + } else { + foreach (QString line, descriptor) { + if (line.startsWith("router ")) { + QStringList parts = line.remove(0,qstrlen("router ")).split(" "); + _name = parts.at(0); + _ip = QHostAddress(parts.at(1)); + _orPort = (quint16)parts.at(2).toUInt(); + _dirPort = (quint16)parts.at(4).toUInt(); + } else if (line.startsWith("platform ")) { + _platform = line.remove(0,qstrlen("platform ")); + } else if (line.startsWith("published ")) { + _published = QDateTime::fromString( + line.remove(0,qstrlen("published ")), + "yyyy-MM-dd HH:mm:ss"); + _published.setTimeSpec(Qt::UTC); + } else if (line.startsWith("opt fingerprint ")) { + _fingerprint = line.remove(0,qstrlen("opt fingerprint ")); + _id = _fingerprint.remove(" "); + } else if (line.startsWith("fingerprint ")) { + _fingerprint = line.remove(0,qstrlen("fingerprint ")); + _id = _fingerprint.remove(" "); + } else if (line.startsWith("uptime ")) { + _uptime = (quint64)line.remove(0,qstrlen("uptime ")).toULongLong(); + } else if (line.startsWith("bandwidth ")) { + QStringList bw = line.remove(0,qstrlen("bandwidth ")).split(" "); + _avgBandwidth = (quint64)bw.at(0).toULongLong(); + _burstBandwidth = (quint64)bw.at(1).toULongLong(); + _observedBandwidth = (quint64)bw.at(2).toULongLong(); + } else if (line.startsWith("contact ")) { + _contact = line.remove(0,qstrlen("contact ")); + } else if (line.startsWith("hibernating ")) { + if (line.remove(0,qstrlen("hibernating ")).trimmed() == "1") { + _status = Hibernating; + } } } } @@ -80,3 +98,12 @@ RouterDescriptor::status() return tr("Offline"); } +void +RouterDescriptor::appendRouterStatusInfo(const RouterStatus &rs) +{ + _id = rs.id(); + _name = rs.name(); + _ip = rs.ipAddress(); + _orPort = rs.orPort(); + _dirPort = rs.dirPort(); +} diff --git a/src/torcontrol/RouterDescriptor.h b/src/torcontrol/RouterDescriptor.h index d4ff868..d0c3400 100644 --- a/src/torcontrol/RouterDescriptor.h +++ b/src/torcontrol/RouterDescriptor.h @@ -22,6 +22,7 @@ #include <QList> #include <QHostAddress> +#include "RouterStatus.h" class RouterDescriptor { @@ -29,16 +30,16 @@ class RouterDescriptor public: /** Possible router states. */ - enum RouterStatus { + enum RouterStatusEnum { Online, /**< Router is online and reachable. */ Hibernating, /**< Router is currently hibernating. */ Offline /**< Router is unresponsive. */ }; /** Default constructor. */ - RouterDescriptor() {} + RouterDescriptor(bool microdesc = false) : _microdesc(microdesc) {} /** Constructor. */ - RouterDescriptor(QStringList descriptor); + RouterDescriptor(QStringList descriptor, bool microdesc = false); /** Returns the router's name. */ QString name() const { return _name; } @@ -86,11 +87,23 @@ public: /** Sets the descriptors status to Offline if <b>offline</b> is true. */ void setOffline(bool offline) { _status = (offline ? Offline : Online); } + /** Microdescriptor */ + /** Returns the onion key for this router */ + QString onionKey() const { return _onionKey; } + /** Returns this router's family */ + QString family() const { return _family; } + /** Returns this router's exit policy */ + QString exitPolicy() const { return _exitPolicy; } + + /** Uses the RouterStatus information to update key elements of the + * descriptor */ + void appendRouterStatusInfo(const RouterStatus &rs); + private: /** Parses this router's descriptor for relevant information. */ void parseDescriptor(QStringList descriptor); - RouterStatus _status; /**< Availability status of this router. */ + RouterStatusEnum _status;/**< Availability status of this router. */ QString _id; /**< Router's descriptor ID. */ QString _name; /**< The router's name. */ QString _fingerprint; /**< Router's fingerprint. */ @@ -105,6 +118,12 @@ private: quint64 _burstBandwidth; /**< Burst bandwidth. */ quint64 _observedBandwidth; /**< Observed bandwidth. */ QString _location; /**< Geographic location information. */ + + /** Microdescriptor info */ + bool _microdesc; /** */ + QString _onionKey; /** Router SSL key */ + QString _exitPolicy; /** Exit policy */ + QString _family; /** Family */ }; #endif diff --git a/src/torcontrol/TorControl.cpp b/src/torcontrol/TorControl.cpp index e95f9c7..b547a40 100644 --- a/src/torcontrol/TorControl.cpp +++ b/src/torcontrol/TorControl.cpp @@ -945,6 +945,20 @@ TorControl::resetConf(QString key, QString *errmsg) return resetConf(QStringList() << key, errmsg); } +bool +TorControl::useMicrodescriptors(QString *errmsg) +{ + if(!errmsg) + errmsg = new QString(); + + QString mdres, fetchres; + if(!getConf("UseMicrodescriptors", mdres, errmsg)) + return false; + if(!getConf("FetchUselessDescriptors", fetchres, errmsg)) + return false; + return (mdres == "1") or (mdres == "auto" and fetchres == "0"); +} + /** Returns an unparsed router descriptor for the router whose fingerprint * matches <b>id</b>. The returned text can later be parsed by the * RouterDescriptor class. If <b>id</b> is invalid, then an empty @@ -952,6 +966,9 @@ TorControl::resetConf(QString key, QString *errmsg) QStringList TorControl::getRouterDescriptorText(const QString &id, QString *errmsg) { + if(useMicrodescriptors(errmsg)) + return getInfo("md/id/" + id, errmsg).toStringList(); + return getInfo("desc/id/" + id, errmsg).toStringList(); } @@ -961,7 +978,7 @@ TorControl::getRouterDescriptorText(const QString &id, QString *errmsg) RouterDescriptor TorControl::getRouterDescriptor(const QString &id, QString *errmsg) { - return RouterDescriptor(getRouterDescriptorText(id, errmsg)); + return RouterDescriptor(getRouterDescriptorText(id, errmsg), useMicrodescriptors()); } /** Returns the status of the router whose fingerprint matches <b>id</b>. If diff --git a/src/torcontrol/TorControl.h b/src/torcontrol/TorControl.h index c16758c..cc486a1 100644 --- a/src/torcontrol/TorControl.h +++ b/src/torcontrol/TorControl.h @@ -168,6 +168,8 @@ public: /** Tells Tor to reset a configuration key back to its default value. */ bool resetConf(QString key, QString *errmsg = 0); + /** Returns true if UseMicrodescriptors is enabled */ + bool useMicrodescriptors(QString *errmsg = 0); /** Returns an unparsed router descriptor for the router whose fingerprint * matches <b>id</b>. The returned text can later be parsed by the * RouterDescriptor class. If <b>id</b> is invalid, then an empty