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 <QMessageBox>
00029 #include <QHeaderView>
00030 #include <vidalia.h>
00031
00032 #include "netviewer.h"
00033
00034 #define IMG_MOVE ":/images/22x22/move-map.png"
00035 #define IMG_ZOOMIN ":/images/22x22/zoom-in.png"
00036 #define IMG_ZOOMOUT ":/images/22x22/zoom-out.png"
00037
00038
00039
00040
00041 #define MIN_RESOLVE_QUEUE_DELAY (10*1000)
00042
00043
00044 #define MAX_RESOLVE_QUEUE_DELAY (30*1000)
00045
00046
00047
00048
00049
00050 NetViewer::NetViewer(QWidget *parent)
00051 : VidaliaWindow("NetViewer", parent)
00052 {
00053
00054 ui.setupUi(this);
00055 #if defined(Q_WS_MAC)
00056 ui.actionHelp->setShortcut(QString("Ctrl+?"));
00057 #endif
00058 #if !defined(Q_WS_WIN)
00059 ui.actionClose->setShortcut(QString("Ctrl+W"));
00060 #endif
00061
00062
00063 _torControl = Vidalia::torControl();
00064 _torControl->setEvent(TorEvents::NewDescriptor, this, true);
00065 _torControl->setEvent(TorEvents::CircuitStatus, this, true);
00066 _torControl->setEvent(TorEvents::StreamStatus, this, true);
00067 _torControl->setEvent(TorEvents::AddressMap, this, true);
00068
00069
00070 ui.treeRouterList->header()->
00071 resizeSection(RouterListWidget::StatusColumn, 25);
00072 ui.treeRouterList->header()->
00073 resizeSection(RouterListWidget::CountryColumn, 25);
00074 ui.treeCircuitList->header()->
00075 resizeSection(CircuitListWidget::ConnectionColumn, 235);
00076
00077
00078 _map = new TorMapWidget();
00079 ui.gridLayout->addWidget(_map);
00080
00081
00082 connect(ui.actionZoomIn, SIGNAL(triggered()), _map, SLOT(zoomIn()));
00083 connect(ui.actionZoomOut, SIGNAL(triggered()), _map, SLOT(zoomOut()));
00084 connect(ui.actionZoomToFit, SIGNAL(triggered()), _map, SLOT(zoomToFit()));
00085
00086
00087
00088
00089 _refreshTimer.setInterval(60*60*1000);
00090 connect(&_refreshTimer, SIGNAL(timeout()), this, SLOT(refresh()));
00091
00092
00093
00094
00095 _minResolveQueueTimer.setSingleShot(true);
00096 connect(&_minResolveQueueTimer, SIGNAL(timeout()), this, SLOT(resolve()));
00097 _maxResolveQueueTimer.setSingleShot(true);
00098 connect(&_maxResolveQueueTimer, SIGNAL(timeout()), this, SLOT(resolve()));
00099
00100
00101 connect(ui.actionHelp, SIGNAL(triggered()), this, SLOT(help()));
00102 connect(ui.actionRefresh, SIGNAL(triggered()), this, SLOT(refresh()));
00103 connect(ui.treeRouterList, SIGNAL(routerSelected(RouterDescriptor)),
00104 this, SLOT(routerSelected(RouterDescriptor)));
00105 connect(ui.treeRouterList, SIGNAL(zoomToRouter(QString)),
00106 _map, SLOT(zoomToRouter(QString)));
00107 connect(ui.treeCircuitList, SIGNAL(circuitSelected(Circuit)),
00108 this, SLOT(circuitSelected(Circuit)));
00109 connect(ui.treeCircuitList, SIGNAL(circuitRemoved(quint64)),
00110 _map, SLOT(removeCircuit(quint64)));
00111 connect(ui.treeCircuitList, SIGNAL(zoomToCircuit(quint64)),
00112 _map, SLOT(zoomToCircuit(quint64)));
00113 connect(ui.treeCircuitList, SIGNAL(closeCircuit(quint64)),
00114 _torControl, SLOT(closeCircuit(quint64)));
00115 connect(ui.treeCircuitList, SIGNAL(closeStream(quint64)),
00116 _torControl, SLOT(closeStream(quint64)));
00117
00118
00119 connect(_torControl, SIGNAL(authenticated()), this, SLOT(onAuthenticated()));
00120 connect(_torControl, SIGNAL(disconnected()), this, SLOT(onDisconnected()));
00121
00122
00123 connect(&_geoip, SIGNAL(resolved(int, QList<GeoIp>)),
00124 this, SLOT(resolved(int, QList<GeoIp>)));
00125 }
00126
00127
00128
00129 void
00130 NetViewer::showWindow()
00131 {
00132 if (!_resolveQueue.isEmpty()) {
00133 _minResolveQueueTimer.start(MIN_RESOLVE_QUEUE_DELAY);
00134 _maxResolveQueueTimer.start(MAX_RESOLVE_QUEUE_DELAY);
00135 }
00136 VidaliaWindow::showWindow();
00137 }
00138
00139
00140 void
00141 NetViewer::onAuthenticated()
00142 {
00143 _geoip.setSocksHost(_torControl->getSocksAddress(),
00144 _torControl->getSocksPort());
00145 refresh();
00146 _refreshTimer.start();
00147 ui.actionRefresh->setEnabled(true);
00148 }
00149
00150
00151 void
00152 NetViewer::onDisconnected()
00153 {
00154 clear();
00155 _refreshTimer.stop();
00156 ui.actionRefresh->setEnabled(false);
00157 }
00158
00159
00160 void
00161 NetViewer::customEvent(QEvent *event)
00162 {
00163 int type = event->type();
00164
00165 if (type == CustomEventType::NewDescriptorEvent) {
00166
00167 NewDescriptorEvent *nde = (NewDescriptorEvent *)event;
00168 loadDescriptors(nde->descriptorIDs());
00169 } else if (type == CustomEventType::CircuitEvent) {
00170
00171 CircuitEvent *ce = (CircuitEvent *)event;
00172 addCircuit(ce->circuit());
00173 } else if (type == CustomEventType::StreamEvent) {
00174
00175 StreamEvent *se = (StreamEvent *)event;
00176 addStream(se->stream());
00177 } else if (type == CustomEventType::AddressMapEvent) {
00178
00179
00180 AddressMapEvent *ae = (AddressMapEvent *)event;
00181 _addressMap.add(ae->to(), ae->from(), ae->expires());
00182 }
00183
00184
00185 _map->update();
00186 }
00187
00188
00189 void
00190 NetViewer::refresh()
00191 {
00192
00193 ui.actionRefresh->setEnabled(false);
00194
00195
00196 clear();
00197
00198
00199 loadDescriptors(_torControl->getRouterIDList());
00200
00201 loadAddressMap();
00202
00203 loadConnections();
00204
00205
00206 ui.actionRefresh->setEnabled(true);
00207 }
00208
00209
00210 void
00211 NetViewer::clear()
00212 {
00213
00214 _resolveMap.clear();
00215 _resolveQueue.clear();
00216
00217 _map->clear();
00218 _map->update();
00219
00220 _addressMap.clear();
00221
00222 ui.treeRouterList->clearRouters();
00223 ui.treeCircuitList->clearCircuits();
00224 ui.textRouterInfo->clear();
00225 }
00226
00227
00228 void
00229 NetViewer::loadAddressMap()
00230 {
00231
00232
00233 _addressMap = _torControl->getAddressMap().reverse();
00234 }
00235
00236
00237 void
00238 NetViewer::loadConnections()
00239 {
00240
00241 QList<Circuit> circuits = _torControl->getCircuits();
00242 foreach (Circuit circuit, circuits) {
00243 addCircuit(circuit);
00244 }
00245
00246 QList<Stream> streams = _torControl->getStreams();
00247 foreach (Stream stream, streams) {
00248 addStream(stream);
00249 }
00250
00251
00252 _map->update();
00253 }
00254
00255
00256 void
00257 NetViewer::addCircuit(Circuit circuit)
00258 {
00259
00260 Circuit circNames = circuitPathNames(circuit);
00261
00262 Circuit circIds = circuitPathIDs(circuit);
00263
00264 ui.treeCircuitList->addCircuit(circuit, circNames.path());
00265 _map->addCircuit(circuit.id(), circIds.hops());
00266 }
00267
00268
00269 void
00270 NetViewer::addStream(Stream stream)
00271 {
00272 QString target = stream.targetAddress();
00273 QHostAddress addr(target);
00274
00275
00276
00277 if (!addr.isNull() && _addressMap.isMapped(target)) {
00278
00279
00280 stream = Stream(stream.id(), stream.status(), stream.circuitId(),
00281 _addressMap.mappedTo(target), stream.targetPort());
00282 }
00283 ui.treeCircuitList->addStream(stream);
00284 }
00285
00286
00287 void
00288 NetViewer::help()
00289 {
00290 Vidalia::help("netview");
00291 }
00292
00293
00294 void
00295 NetViewer::loadDescriptors(QStringList ids)
00296 {
00297
00298 QList<RouterDescriptor> rds = _torControl->getDescriptorListById(ids);
00299
00300 vInfo("Loading %1 server descriptors for the network map.")
00301 .arg(rds.size());
00302 foreach (RouterDescriptor rd, rds) {
00303
00304 if (!rd.isEmpty()) {
00305 addRouter(rd);
00306 }
00307 }
00308 }
00309
00310
00311
00312 void
00313 NetViewer::addRouter(RouterDescriptor rd)
00314 {
00315
00316 ui.treeRouterList->addRouter(rd);
00317
00318
00319 addToResolveQueue(rd.ip(), rd.id());
00320 }
00321
00322
00323 void
00324 NetViewer::addToResolveQueue(QHostAddress ip, QString id)
00325 {
00326 QString ipstr = ip.toString();
00327 if (!_resolveMap.values(ipstr).contains(id)) {
00328
00329 _resolveMap.insertMulti(ipstr, id);
00330 }
00331
00332 if (!_resolveQueue.contains(ip) && !_geoip.resolveFromCache(ip)) {
00333
00334 _resolveQueue << ip;
00335
00336
00337
00338 _minResolveQueueTimer.start(MIN_RESOLVE_QUEUE_DELAY);
00339
00340
00341
00342
00343 if (_resolveQueue.size() == 1) {
00344 _maxResolveQueueTimer.start(MAX_RESOLVE_QUEUE_DELAY);
00345 }
00346 }
00347 }
00348
00349
00350
00351 void
00352 NetViewer::circuitSelected(Circuit circuit)
00353 {
00354
00355 ui.treeRouterList->deselectAll();
00356 ui.textRouterInfo->clear();
00357 _map->deselectAll();
00358
00359
00360 _map->selectCircuit(circuit.id());
00361
00362 QList<RouterDescriptor> routers;
00363
00364 foreach (QString router, circuit.hops()) {
00365
00366 RouterListItem *item = (router.startsWith("$") ?
00367 ui.treeRouterList->findRouterById(router.mid(1))
00368 : ui.treeRouterList->findRouterByName(router));
00369 if (item) {
00370 routers.append(item->descriptor());
00371 }
00372 }
00373
00374 ui.textRouterInfo->display(routers);
00375 }
00376
00377
00378 void
00379 NetViewer::routerSelected(RouterDescriptor router)
00380 {
00381 _map->deselectAll();
00382 ui.textRouterInfo->clear();
00383 ui.textRouterInfo->display(router);
00384 _map->selectRouter(router.id());
00385 }
00386
00387
00388 void
00389 NetViewer::resolve()
00390 {
00391 if (!_resolveQueue.isEmpty()) {
00392
00393
00394 if (isVisible() ||
00395 (_resolveQueue.size() >= ui.treeRouterList->topLevelItemCount()/4)) {
00396 vInfo("Sending GeoIP request for %1 IP addresses.")
00397 .arg(_resolveQueue.size());
00398
00399 _geoip.resolve(_resolveQueue);
00400 _resolveQueue.clear();
00401 }
00402 }
00403
00404
00405 _minResolveQueueTimer.stop();
00406 _maxResolveQueueTimer.stop();
00407 }
00408
00409
00410 void
00411 NetViewer::resolved(int id, QList<GeoIp> geoips)
00412 {
00413 Q_UNUSED(id);
00414 QString ip;
00415 RouterListItem *router;
00416
00417 foreach (GeoIp geoip, geoips) {
00418
00419 ip = geoip.ip().toString();
00420 QList<QString> ids = _resolveMap.values(ip);
00421 _resolveMap.remove(ip);
00422 if (geoip.isUnknown())
00423 continue;
00424
00425
00426
00427 foreach (QString id, ids) {
00428 router = ui.treeRouterList->findRouterById(id);
00429 if (router) {
00430
00431 router->setLocation(geoip);
00432
00433 _map->addRouter(router->id(), geoip.latitude(), geoip.longitude());
00434 }
00435 }
00436 }
00437
00438
00439 foreach (Circuit circuit, ui.treeCircuitList->circuits()) {
00440 _map->addCircuit(circuit.id(), circuitPathIDs(circuit).hops());
00441 }
00442
00443
00444 _map->update();
00445 }
00446
00447
00448
00449
00450 Circuit
00451 NetViewer::circuitPathIDs(Circuit circ)
00452 {
00453 QStringList path = circ.hops();
00454 QStringList ids;
00455 RouterDescriptor rd;
00456 quint32 torVersion;
00457
00458 torVersion = _torControl->getTorVersion();
00459 foreach (QString hop, path) {
00460 if (hop.startsWith("$")) {
00461
00462 hop.remove(0,1);
00463 } else {
00464 if (torVersion < 0x00010202) {
00465
00466
00467
00468
00469
00470 RouterListItem *item = ui.treeRouterList->findRouterByName(hop);
00471 if (item) {
00472 rd = item->descriptor();
00473 } else {
00474
00475
00476 rd = _torControl->getDescriptorByName(hop);
00477 if (!rd.isEmpty()) {
00478
00479 addRouter(rd);
00480 }
00481 }
00482 } else {
00483
00484 rd = _torControl->getDescriptorByName(hop);
00485 }
00486 hop = (rd.isEmpty() ? hop : rd.id());
00487 }
00488 ids << hop;
00489 }
00490 return Circuit(circ.id(), circ.status(), ids);
00491 }
00492
00493
00494
00495
00496 Circuit
00497 NetViewer::circuitPathNames(Circuit circ)
00498 {
00499 QStringList path = circ.hops();
00500 QStringList names;
00501 RouterDescriptor rd;
00502
00503 foreach (QString hop, path) {
00504 if (hop.startsWith("$")) {
00505
00506 RouterListItem *item = ui.treeRouterList->findRouterById(hop.mid(1));
00507 if (item) {
00508 rd = item->descriptor();
00509 } else {
00510
00511
00512 rd = _torControl->getDescriptorById(hop);
00513 if (!rd.isEmpty()) {
00514
00515 addRouter(rd);
00516 }
00517 }
00518 hop = (rd.isEmpty() ? hop : rd.name());
00519 }
00520 names << hop;
00521 }
00522 return Circuit(circ.id(), circ.status(), names);
00523 }
00524