Vidalia  0.2.21
RouterStatus.cpp
Go to the documentation of this file.
1 /*
2 ** This file is part of Vidalia, and is subject to the license terms in the
3 ** LICENSE file, found in the top level directory of this distribution. If
4 ** you did not receive the LICENSE file with this file, you may obtain it
5 ** from the Vidalia source package distributed by the Vidalia Project at
6 ** http://www.torproject.org/projects/vidalia.html. No part of Vidalia,
7 ** including this file, may be copied, modified, propagated, or distributed
8 ** except according to the terms described in the LICENSE file.
9 */
10 
11 /*
12 ** \file RouterStatus.cpp
13 ** \brief Parses a blob of router status text from Tor
14 */
15 
16 #include "RouterStatus.h"
17 
18 #include "stringutil.h"
19 
20 /** Defines the time format used when parsing the published date and time from
21  * a router's status. */
22 #define TIME_FORMAT "yyyy-MM-dd HH:mm:ss"
23 
24 
25 /** Constructor. Parses <b>status</b> for router status information. The given
26  * string should match the router status entry format from Tor's dir-spec.txt.
27  * The currently recognized lines are:
28  *
29  * "r" SP nickname SP identity SP digest SP publication SP IP SP ORPort
30  * SP DirPort NL
31  * "s" SP Flags NL
32  *
33  * Unrecognized lines are currently ignored.
34  *
35  * */
36 RouterStatus::RouterStatus(const QStringList &status)
37 {
38  bool ok;
39 
40  _valid = false;
41  _flags = 0;
42 
43  _bandwidth = 0;
44 
45  foreach (QString line, status) {
46  if (line.startsWith("r ")) {
47  QStringList parts = line.split(" ", QString::SkipEmptyParts);
48  if (parts.size() < 9)
49  return;
50 
51  /* Nickname */
52  _name = parts.at(1);
53  /* Identity key digest */
54  _id = base16_encode(QByteArray::fromBase64(parts.at(2).toAscii()));
55  if (_id.isEmpty())
56  return;
57  /* Most recent descriptor digest */
58  _digest = base16_encode(QByteArray::fromBase64(parts.at(3).toAscii()));
59  if (_digest.isEmpty())
60  return;
61  /* Most recent publication date */
62  _published = QDateTime::fromString(parts.at(4) + " " + parts.at(5),
63  TIME_FORMAT);
64  if (!_published.isValid())
65  return;
66  /* IP address */
67  _ipAddress = QHostAddress(parts.at(6));
68  if (_ipAddress.isNull())
69  return;
70  /* ORPort */
71  _orPort = parts.at(7).toUInt(&ok);
72  if (!ok)
73  return;
74  /* DirPort */
75  _dirPort = parts.at(8).toUInt(&ok);
76  if (!ok)
77  return;
78 
79  _valid = true;
80  } else if (line.startsWith("s ")) {
81  /* Status flags */
82  QStringList flags = line.split(" ", QString::SkipEmptyParts);
83  flags.removeFirst(); /* Remove the "s" */
84 
85  foreach (QString flag, flags) {
86  _flags |= flagValue(flag);
87  }
88  } else if (line.startsWith("w ")) {
89  /* Status flags */
90  QStringList parts = line.split(" ", QString::SkipEmptyParts);
91  parts.removeFirst(); /* Remove the "w" */
92 
93  if(parts.size() > 0) {
94  QStringList bw = parts.at(0).split("=", QString::SkipEmptyParts);
95  if(bw.size() == 2) {
96  _bandwidth = (quint64)bw.at(1).toULongLong();
97  }
98  }
99  }
100  }
101 }
102 
103 /** Returns a Flags enum value for the given router status <b>flag</b>. If
104  * <b>flag</b> is not recognized, then <i>Unknown</i> is returned. */
106 RouterStatus::flagValue(const QString &flag)
107 {
108  if (!flag.compare("Authority", Qt::CaseInsensitive))
109  return Authority;
110  if (!flag.compare("BadExit", Qt::CaseInsensitive))
111  return BadExit;
112  if (!flag.compare("BadDirectory", Qt::CaseInsensitive))
113  return BadDirectory;
114  if (!flag.compare("Exit", Qt::CaseInsensitive))
115  return Exit;
116  if (!flag.compare("Fast", Qt::CaseInsensitive))
117  return Fast;
118  if (!flag.compare("Guard", Qt::CaseInsensitive))
119  return Guard;
120  if (!flag.compare("HSDir", Qt::CaseInsensitive))
121  return HSDir;
122  if (!flag.compare("Named", Qt::CaseInsensitive))
123  return Named;
124  if (!flag.compare("Running", Qt::CaseInsensitive))
125  return Running;
126  if (!flag.compare("Stable", Qt::CaseInsensitive))
127  return Stable;
128  if (!flag.compare("Valid", Qt::CaseInsensitive))
129  return Valid;
130  if (!flag.compare("V2Dir", Qt::CaseInsensitive))
131  return V2Dir;
132  if (!flag.compare("V3Dir", Qt::CaseInsensitive))
133  return V3Dir;
134  return Unknown; /* Unknown status flag */
135 }
136