00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "TorEvents.h"
00019 #include "ControlReply.h"
00020 #include "ReplyLine.h"
00021 #include "Circuit.h"
00022 #include "Stream.h"
00023 #include "BootstrapStatus.h"
00024
00025 #include "stringutil.h"
00026
00027 #include <QHostAddress>
00028 #include <QMetaType>
00029
00030
00031 #define DATE_FMT "\"yyyy-MM-dd HH:mm:ss\""
00032
00033
00034
00035 TorEvents::TorEvents(QObject *parent)
00036 : QObject(parent)
00037 {
00038 qRegisterMetaType<tc::Severity>();
00039 qRegisterMetaType<tc::SocksError>();
00040 qRegisterMetaType<tc::TorVersionStatus>();
00041
00042 qRegisterMetaType<BootstrapStatus>("BootstrapStatus");
00043 qRegisterMetaType<Circuit>("Circuit");
00044 qRegisterMetaType<Stream>("Stream");
00045
00046 qRegisterMetaType<QHostAddress>("QHostAddress");
00047 qRegisterMetaType<QDateTime>("QDateTime");
00048 }
00049
00050
00051 QString
00052 TorEvents::toString(Event e)
00053 {
00054 QString event;
00055 switch (e) {
00056 case Bandwidth: event = "BW"; break;
00057 case LogDebug: event = "DEBUG"; break;
00058 case LogInfo: event = "INFO"; break;
00059 case LogNotice: event = "NOTICE"; break;
00060 case LogWarn: event = "WARN"; break;
00061 case LogError: event = "ERR"; break;
00062 case CircuitStatus: event = "CIRC"; break;
00063 case StreamStatus: event = "STREAM"; break;
00064 case NewDescriptor: event = "NEWDESC"; break;
00065 case AddressMap: event = "ADDRMAP"; break;
00066 case GeneralStatus: event = "STATUS_GENERAL"; break;
00067 case ClientStatus: event = "STATUS_CLIENT"; break;
00068 case ServerStatus: event = "STATUS_SERVER"; break;
00069 default: event = "UNKNOWN"; break;
00070 }
00071 return event;
00072 }
00073
00074
00075 TorEvents::Event
00076 TorEvents::toTorEvent(const QString &event)
00077 {
00078 Event e;
00079 if (event == "BW") {
00080 e = Bandwidth;
00081 } else if (event == "CIRC") {
00082 e = CircuitStatus;
00083 } else if (event == "STREAM") {
00084 e = StreamStatus;
00085 } else if (event == "DEBUG") {
00086 e = LogDebug;
00087 } else if (event == "INFO") {
00088 e = LogInfo;
00089 } else if (event == "NOTICE") {
00090 e = LogNotice;
00091 } else if (event == "WARN") {
00092 e = LogWarn;
00093 } else if (event == "ERR") {
00094 e = LogError;
00095 } else if (event == "NEWDESC") {
00096 e = NewDescriptor;
00097 } else if (event == "ADDRMAP") {
00098 e = AddressMap;
00099 } else if (event == "STATUS_GENERAL") {
00100 e = GeneralStatus;
00101 } else if (event == "STATUS_CLIENT") {
00102 e = ClientStatus;
00103 } else if (event == "STATUS_SERVER") {
00104 e = ServerStatus;
00105 } else {
00106 e = Unknown;
00107 }
00108 return e;
00109 }
00110
00111
00112
00113 TorEvents::Event
00114 TorEvents::parseEventType(const ReplyLine &line)
00115 {
00116 QString msg = line.getMessage();
00117 int i = msg.indexOf(" ");
00118 return toTorEvent(msg.mid(0, i));
00119 }
00120
00121
00122
00123
00124 void
00125 TorEvents::handleEvent(const ControlReply &reply)
00126 {
00127 foreach(ReplyLine line, reply.getLines()) {
00128 switch (parseEventType(line)) {
00129 case Bandwidth: handleBandwidthUpdate(line); break;
00130 case CircuitStatus: handleCircuitStatus(line); break;
00131 case StreamStatus: handleStreamStatus(line); break;
00132 case NewDescriptor: handleNewDescriptor(line); break;
00133 case AddressMap: handleAddressMap(line); break;
00134
00135 case GeneralStatus:
00136 handleStatusEvent(GeneralStatus, line); break;
00137 case ClientStatus:
00138 handleStatusEvent(ClientStatus, line); break;
00139 case ServerStatus:
00140 handleStatusEvent(ServerStatus, line); break;
00141
00142 case LogDebug:
00143 case LogInfo:
00144 case LogNotice:
00145 case LogWarn:
00146 case LogError:
00147 handleLogMessage(line); break;
00148 default: break;
00149 }
00150 }
00151 }
00152
00153
00154
00155
00156
00157
00158
00159
00160 void
00161 TorEvents::handleBandwidthUpdate(const ReplyLine &line)
00162 {
00163 QStringList msg = line.getMessage().split(" ");
00164 if (msg.size() >= 3) {
00165 quint64 bytesIn = (quint64)msg.at(1).toULongLong();
00166 quint64 bytesOut = (quint64)msg.at(2).toULongLong();
00167
00168
00169 emit bandwidthUpdate(bytesIn, bytesOut);
00170 }
00171 }
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184 void
00185 TorEvents::handleCircuitStatus(const ReplyLine &line)
00186 {
00187 QString msg = line.getMessage().trimmed();
00188 int i = msg.indexOf(" ") + 1;
00189 if (i > 0) {
00190
00191 Circuit circ(msg.mid(i));
00192 if (circ.isValid())
00193 emit circuitStatusChanged(circ);
00194 }
00195 }
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213 void
00214 TorEvents::handleStreamStatus(const ReplyLine &line)
00215 {
00216 QString msg = line.getMessage().trimmed();
00217 int i = msg.indexOf(" ") + 1;
00218 if (i > 0) {
00219 Stream stream = Stream::fromString(msg.mid(i));
00220 if (stream.isValid())
00221 emit streamStatusChanged(stream);
00222 }
00223 }
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233 void
00234 TorEvents::handleLogMessage(const ReplyLine &line)
00235 {
00236 QString msg = line.getMessage();
00237 int i = msg.indexOf(" ");
00238 tc::Severity severity = tc::severityFromString(msg.mid(0, i));
00239 QString logLine = (line.getData().size() > 0 ? line.getData().join("\n") :
00240 msg.mid(i+1));
00241
00242 emit logMessage(severity, logLine);
00243 }
00244
00245
00246
00247
00248
00249
00250 void
00251 TorEvents::handleNewDescriptor(const ReplyLine &line)
00252 {
00253 QString descs = line.getMessage();
00254 QStringList descList = descs.mid(descs.indexOf(" ")+1).split(" ");
00255 emit newDescriptors(descList);
00256 }
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266 void
00267 TorEvents::handleAddressMap(const ReplyLine &line)
00268 {
00269 QStringList msg = line.getMessage().split(" ");
00270 if (msg.size() >= 4) {
00271 QDateTime expires;
00272 if (msg.size() >= 5 && msg.at(3) != "NEVER")
00273 expires = QDateTime::fromString(msg.at(3) + " " + msg.at(4), DATE_FMT);
00274 emit addressMapped(msg.at(1), msg.at(2), expires);
00275 }
00276 }
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291 void
00292 TorEvents::handleStatusEvent(Event e, const ReplyLine &line)
00293 {
00294 QString status;
00295 tc::Severity severity;
00296 QHash<QString,QString> args;
00297 QString msg = line.getMessage();
00298
00299 severity = tc::severityFromString(msg.section(' ', 1, 1));
00300 status = msg.section(' ', 2, 2);
00301 args = string_parse_keyvals(msg.section(' ', 3));
00302 switch (e) {
00303 case ClientStatus:
00304 handleClientStatusEvent(severity, status, args);
00305 break;
00306
00307 case ServerStatus:
00308 handleServerStatusEvent(severity, status, args);
00309 break;
00310
00311 case GeneralStatus:
00312 handleGeneralStatusEvent(severity, status, args);
00313 break;
00314
00315 default:
00316 break;
00317 }
00318 }
00319
00320
00321 void
00322 TorEvents::handleGeneralStatusEvent(tc::Severity severity,
00323 const QString &action,
00324 const QHash<QString,QString> &args)
00325 {
00326 if (! action.compare("DANGEROUS_TOR_VERSION", Qt::CaseInsensitive)) {
00327 QString reason = args.value("REASON");
00328 QString current = args.value("CURRENT");
00329 QStringList recommended = args.value("RECOMMENDED")
00330 .split(",", QString::SkipEmptyParts);
00331 if (! reason.compare("NEW", Qt::CaseInsensitive))
00332 emit dangerousTorVersion(tc::NewTorVersion, current, recommended);
00333 else if (! reason.compare("UNRECOMMENDED", Qt::CaseInsensitive))
00334 emit dangerousTorVersion(tc::UnrecommendedTorVersion, current, recommended);
00335 else if (! reason.compare("OBSOLETE", Qt::CaseInsensitive)
00336 || ! reason.compare("OLD", Qt::CaseInsensitive))
00337 emit dangerousTorVersion(tc::ObsoleteTorVersion, current, recommended);
00338 } else if (! action.compare("CLOCK_SKEW", Qt::CaseInsensitive)) {
00339 int skew;
00340 bool ok = false;
00341 if (args.contains("SKEW"))
00342 skew = args.value("SKEW").toInt(&ok);
00343 else if (args.contains("MIN_SKEW"))
00344 skew = args.value("MIN_SKEW").toInt(&ok);
00345 if (ok)
00346 emit clockSkewed(skew, args.value("SOURCE"));
00347 } else if (! action.compare("BUG", Qt::CaseInsensitive)) {
00348 emit bug(args.value("REASON"));
00349 }
00350 }
00351
00352
00353 void
00354 TorEvents::handleClientStatusEvent(tc::Severity severity,
00355 const QString &action,
00356 const QHash<QString,QString> &args)
00357 {
00358 if (! action.compare("CIRCUIT_ESTABLISHED", Qt::CaseInsensitive)) {
00359 emit circuitEstablished();
00360 } else if (! action.compare("DANGEROUS_PORT", Qt::CaseInsensitive)) {
00361 bool reject = ! args.value("RESULT").compare("REJECT", Qt::CaseInsensitive);
00362 emit dangerousPort(args.value("PORT").toUInt(), reject);
00363 } else if (! action.compare("DANGEROUS_SOCKS", Qt::CaseInsensitive)) {
00364 emit socksError(tc::DangerousSocksTypeError, args.value("ADDRESS"));
00365 } else if (! action.compare("SOCKS_UNKNOWN_PROTOCOL", Qt::CaseInsensitive)) {
00366 emit socksError(tc::UnknownSocksProtocolError, QString());
00367 } else if (! action.compare("SOCKS_BAD_HOSTNAME", Qt::CaseInsensitive)) {
00368 emit socksError(tc::BadSocksHostnameError, args.value("HOSTNAME"));
00369 } else if (! action.compare("BOOTSTRAP", Qt::CaseInsensitive)) {
00370 BootstrapStatus status
00371 = BootstrapStatus(severity,
00372 BootstrapStatus::statusFromString(args.value("TAG")),
00373 args.value("PROGRESS").toInt(),
00374 args.value("SUMMARY"),
00375 args.value("WARNING"),
00376 tc::connectionStatusReasonFromString(args.value("REASON")),
00377 BootstrapStatus::actionFromString(
00378 args.value("RECOMMENDATION")));
00379 emit bootstrapStatusChanged(status);
00380 }
00381 }
00382
00383
00384 void
00385 TorEvents::handleServerStatusEvent(tc::Severity severity,
00386 const QString &action,
00387 const QHash<QString,QString> &args)
00388 {
00389 if (! action.compare("EXTERNAL_ADDRESS", Qt::CaseInsensitive)) {
00390 emit externalAddressChanged(QHostAddress(args.value("ADDRESS")),
00391 args.value("HOSTNAME"));
00392 } else if (! action.compare("CHECKING_REACHABILITY", Qt::CaseInsensitive)) {
00393 if (args.contains("ORADDRESS")) {
00394 QPair<QHostAddress,quint16> pair = splitAddress(args.value("ORADDRESS"));
00395 if (! pair.first.isNull())
00396 emit checkingOrPortReachability(pair.first, pair.second);
00397 } else if (args.contains("DIRADDRESS")) {
00398 QPair<QHostAddress,quint16> pair = splitAddress(args.value("DIRADDRESS"));
00399 if (! pair.first.isNull())
00400 emit checkingDirPortReachability(pair.first, pair.second);
00401 }
00402 } else if (! action.compare("REACHABILITY_SUCCEEDED", Qt::CaseInsensitive)) {
00403 if (args.contains("ORADDRESS")) {
00404 QPair<QHostAddress,quint16> pair = splitAddress(args.value("ORADDRESS"));
00405 if (! pair.first.isNull())
00406 emit orPortReachabilityFinished(pair.first, pair.second, true);
00407 } else if (args.contains("DIRADDRESS")) {
00408 QPair<QHostAddress,quint16> pair = splitAddress(args.value("DIRADDRESS"));
00409 if (! pair.first.isNull())
00410 emit dirPortReachabilityFinished(pair.first, pair.second, true);
00411 }
00412 } else if (! action.compare("REACHABILITY_FAILED", Qt::CaseInsensitive)) {
00413 if (args.contains("ORADDRESS")) {
00414 QPair<QHostAddress,quint16> pair = splitAddress(args.value("ORADDRESS"));
00415 if (! pair.first.isNull())
00416 emit orPortReachabilityFinished(pair.first, pair.second, false);
00417 } else if (args.contains("DIRADDRESS")) {
00418 QPair<QHostAddress,quint16> pair = splitAddress(args.value("DIRADDRESS"));
00419 if (! pair.first.isNull())
00420 emit dirPortReachabilityFinished(pair.first, pair.second, false);
00421 }
00422 } else if (! action.compare("GOOD_SERVER_DESCRIPTOR", Qt::CaseInsensitive)) {
00423 emit serverDescriptorAccepted();
00424 } else if (! action.compare("ACCEPTED_SERVER_DESCRIPTOR", Qt::CaseInsensitive)) {
00425 QPair<QHostAddress,quint16> pair = splitAddress(args.value("DIRAUTH"));
00426 if (! pair.first.isNull())
00427 emit serverDescriptorAccepted(pair.first, pair.second);
00428 } else if (! action.compare("BAD_SERVER_DESCRIPTOR", Qt::CaseInsensitive)) {
00429 QPair<QHostAddress,quint16> pair = splitAddress(args.value("DIRAUTH"));
00430 if (! pair.first.isNull())
00431 emit serverDescriptorRejected(pair.first, pair.second,
00432 args.value("REASON"));
00433 } else if (! action.compare("DNS_HIJACKED", Qt::CaseInsensitive)) {
00434 emit dnsHijacked();
00435 } else if (! action.compare("DNS_USELESS", Qt::CaseInsensitive)) {
00436 emit dnsUseless();
00437 }
00438 }
00439
00440
00441
00442
00443 QPair<QHostAddress,quint16>
00444 TorEvents::splitAddress(const QString &address)
00445 {
00446 bool ok;
00447 int idx = address.indexOf(":");
00448 if (idx <= 0 || idx >= address.length()-1)
00449 return QPair<QHostAddress,quint16>();
00450
00451 QHostAddress ip = QHostAddress(address.mid(0, idx));
00452 quint16 port = static_cast<quint16>(address.mid(idx+1).toUInt(&ok));
00453 if (ip.isNull() || ! ok)
00454 return QPair<QHostAddress,quint16>();
00455 return QPair<QHostAddress,quint16>(ip, port);
00456 }
00457
00458