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 #define MAX_EVENTS_TIMEOUT 25
00041
00042
00043
00044 #define RESOLVE_QUEUE_DELAY 3000
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 ui.actionClose->setShortcut(QString("Ctrl+W"));
00058 #endif
00059
00060
00061 _torControl = Vidalia::torControl();
00062 _torControl->setEvent(TorEvents::NewDescriptor, this, true);
00063 _torControl->setEvent(TorEvents::CircuitStatus, this, true);
00064 _torControl->setEvent(TorEvents::StreamStatus, this, true);
00065
00066
00067 ui.treeRouterList->header()->
00068 resizeSection(RouterListWidget::StatusColumn,
00069 RouterListWidget::StatusColumnWidth);
00070 ui.treeCircuitList->header()->
00071 resizeSection(CircuitListWidget::ConnectionColumn,
00072 CircuitListWidget::ConnectionColumnWidth);
00073
00074
00075 _map = new TorMapWidget();
00076 ui.gridLayout->addWidget(_map);
00077
00078
00079 connect(ui.actionZoomIn, SIGNAL(triggered()), _map, SLOT(zoomIn()));
00080 connect(ui.actionZoomOut, SIGNAL(triggered()), _map, SLOT(zoomOut()));
00081 connect(ui.actionZoomToFit, SIGNAL(triggered()), _map, SLOT(zoomToFit()));
00082
00083
00084
00085
00086 _refreshTimer.setInterval(60*60*1000);
00087 connect(&_refreshTimer, SIGNAL(timeout()), this, SLOT(refresh()));
00088
00089
00090
00091
00092 _resolveQueueTimer.setSingleShot(true);
00093 connect(&_resolveQueueTimer, SIGNAL(timeout()), this, SLOT(resolve()));
00094
00095
00096 connect(ui.actionHelp, SIGNAL(triggered()), this, SLOT(help()));
00097 connect(ui.actionRefresh, SIGNAL(triggered()), this, SLOT(refresh()));
00098 connect(ui.treeRouterList, SIGNAL(routerSelected(RouterDescriptor)),
00099 this, SLOT(routerSelected(RouterDescriptor)));
00100 connect(ui.treeCircuitList, SIGNAL(circuitSelected(Circuit)),
00101 this, SLOT(circuitSelected(Circuit)));
00102 connect(ui.treeCircuitList, SIGNAL(circuitRemoved(quint64)),
00103 _map, SLOT(removeCircuit(quint64)));
00104
00105
00106 connect(_torControl, SIGNAL(connected(bool)), ui.actionRefresh, SLOT(setEnabled(bool)));
00107 connect(_torControl, SIGNAL(connected()), this, SLOT(gotConnected()));
00108 connect(_torControl, SIGNAL(disconnected()), this, SLOT(gotDisconnected()));
00109
00110
00111 connect(&_geoip, SIGNAL(resolved(int, QList<GeoIp>)),
00112 this, SLOT(resolved(int, QList<GeoIp>)));
00113 }
00114
00115
00116 void
00117 NetViewer::gotDisconnected()
00118 {
00119 clear();
00120 _refreshTimer.stop();
00121 }
00122
00123
00124 void
00125 NetViewer::gotConnected()
00126 {
00127 refresh();
00128 _refreshTimer.start();
00129 }
00130
00131
00132 void
00133 NetViewer::customEvent(QEvent *event)
00134 {
00135 int type = event->type();
00136
00137 if (type == CustomEventType::NewDescriptorEvent) {
00138
00139 NewDescriptorEvent *nde = (NewDescriptorEvent *)event;
00140 loadDescriptors(nde->descriptorIDs());
00141
00142 } else if (type == CustomEventType::CircuitEvent) {
00143
00144 CircuitEvent *ce = (CircuitEvent *)event;
00145 addCircuit(ce->circuit());
00146
00147 } else if (type == CustomEventType::StreamEvent) {
00148
00149 StreamEvent *se = (StreamEvent *)event;
00150 ui.treeCircuitList->addStream(se->stream());
00151 }
00152
00153
00154 _map->update();
00155 }
00156
00157
00158 void
00159 NetViewer::refresh()
00160 {
00161
00162 ui.actionRefresh->setEnabled(false);
00163
00164
00165 clear();
00166
00167
00168 loadDescriptors(_torControl->getRouterIDList());
00169
00170
00171 loadConnections();
00172
00173
00174 ui.actionRefresh->setEnabled(true);
00175 }
00176
00177
00178 void
00179 NetViewer::clear()
00180 {
00181
00182 _resolveMap.clear();
00183 _resolveQueue.clear();
00184
00185 _map->clear();
00186 _map->update();
00187
00188 ui.treeRouterList->clearRouters();
00189 ui.treeCircuitList->clearCircuits();
00190 ui.textRouterInfo->clear();
00191 }
00192
00193
00194 void
00195 NetViewer::loadConnections()
00196 {
00197
00198 QList<Circuit> circuits = _torControl->getCircuits();
00199 foreach (Circuit circuit, circuits) {
00200 addCircuit(circuit);
00201 }
00202
00203 QList<Stream> streams = _torControl->getStreams();
00204 foreach (Stream stream, streams) {
00205 ui.treeCircuitList->addStream(stream);
00206 }
00207
00208
00209 _map->update();
00210 }
00211
00212
00213 void
00214 NetViewer::addCircuit(Circuit circuit)
00215 {
00216
00217 Circuit circNames = circuitPathNames(circuit);
00218
00219 Circuit circIds = circuitPathIDs(circuit);
00220
00221 ui.treeCircuitList->addCircuit(circNames);
00222 _map->addCircuit(circuit.id(), circIds.hops());
00223 }
00224
00225
00226 void
00227 NetViewer::help()
00228 {
00229 Vidalia::help("netview");
00230 }
00231
00232
00233 void
00234 NetViewer::loadDescriptors(QStringList ids)
00235 {
00236
00237 QList<RouterDescriptor> rds = _torControl->getDescriptorListById(ids);
00238
00239 foreach (RouterDescriptor rd, rds) {
00240
00241 if (!rd.isEmpty()) {
00242 addRouter(rd);
00243 }
00244 }
00245 }
00246
00247
00248
00249 void
00250 NetViewer::addRouter(RouterDescriptor rd)
00251 {
00252
00253 ui.treeRouterList->addRouter(rd);
00254
00255
00256 QHostAddress ip(rd.ip());
00257 if (!_resolveQueue.contains(ip)) {
00258 _resolveQueue << ip;
00259 }
00260 if (!_resolveMap.values(rd.ip()).contains(rd.id())) {
00261 _resolveMap.insertMulti(rd.ip(), rd.id());
00262 }
00263
00264
00265
00266
00267 if (!_resolveQueue.isEmpty()) {
00268
00269
00270 _resolveQueueTimer.start(RESOLVE_QUEUE_DELAY);
00271 }
00272 }
00273
00274
00275
00276 void
00277 NetViewer::circuitSelected(Circuit circuit)
00278 {
00279
00280 ui.treeRouterList->deselectAll();
00281 ui.textRouterInfo->clear();
00282 _map->deselectAll();
00283
00284
00285 _map->selectCircuit(circuit.id());
00286
00287 QList<RouterDescriptor> routers;
00288
00289 foreach (QString router, circuit.hops()) {
00290
00291 RouterListItem *item = ui.treeRouterList->findRouterByName(router);
00292 if (item) {
00293 routers.append(item->descriptor());
00294 }
00295 }
00296
00297 ui.textRouterInfo->display(routers);
00298 }
00299
00300
00301 void
00302 NetViewer::routerSelected(RouterDescriptor router)
00303 {
00304 _map->deselectAll();
00305 ui.textRouterInfo->clear();
00306 ui.textRouterInfo->display(router);
00307 _map->selectRouter(router.name());
00308 }
00309
00310
00311 void
00312 NetViewer::resolve()
00313 {
00314 if (!_resolveQueue.isEmpty()) {
00315 _geoip.resolve(_resolveQueue);
00316 _resolveQueue.clear();
00317 }
00318 }
00319
00320
00321 void
00322 NetViewer::resolved(int id, QList<GeoIp> geoips)
00323 {
00324 Q_UNUSED(id);
00325 QString ip;
00326 RouterListItem *router;
00327
00328 foreach (GeoIp geoip, geoips) {
00329
00330 ip = geoip.ip().toString();
00331 QList<QString> ids = _resolveMap.values(ip);
00332
00333
00334
00335 foreach (QString id, ids) {
00336 router = ui.treeRouterList->findRouterById(id);
00337 if (router) {
00338
00339 router->setLocation(geoip.toLocation());
00340
00341 _map->addRouter(router->id(), geoip.latitude(), geoip.longitude());
00342 }
00343 }
00344 _resolveMap.remove(ip);
00345 }
00346
00347
00348 foreach (Circuit circuit, ui.treeCircuitList->circuits()) {
00349 _map->addCircuit(circuit.id(), circuitPathIDs(circuit).hops());
00350 }
00351
00352
00353 _map->update();
00354 }
00355
00356
00357
00358
00359 Circuit
00360 NetViewer::circuitPathIDs(Circuit circ)
00361 {
00362 QStringList path = circ.hops();
00363 QStringList ids;
00364 RouterDescriptor rd;
00365 quint32 torVersion;
00366
00367 torVersion = _torControl->getTorVersion();
00368 foreach (QString hop, path) {
00369 if (!hop.startsWith("$")) {
00370 if (torVersion < 0x00010202) {
00371
00372
00373
00374
00375
00376 RouterListItem *item = ui.treeRouterList->findRouterByName(hop);
00377 if (item) {
00378 rd = item->descriptor();
00379 } else {
00380
00381
00382 rd = _torControl->getDescriptorByName(hop);
00383 if (!rd.isEmpty()) {
00384
00385 addRouter(rd);
00386 }
00387 }
00388 } else {
00389
00390 rd = _torControl->getDescriptorByName(hop);
00391 }
00392 hop = (rd.isEmpty() ? hop : rd.id());
00393 }
00394 ids << hop;
00395 }
00396 return Circuit(circ.id(), circ.status(), ids);
00397 }
00398
00399
00400
00401
00402 Circuit
00403 NetViewer::circuitPathNames(Circuit circ)
00404 {
00405 QStringList path = circ.hops();
00406 QStringList names;
00407 RouterDescriptor rd;
00408
00409 foreach (QString hop, path) {
00410 if (hop.startsWith("$")) {
00411
00412 RouterListItem *item = ui.treeRouterList->findRouterById(hop.mid(1));
00413 if (item) {
00414 rd = item->descriptor();
00415 } else {
00416
00417
00418 rd = _torControl->getDescriptorById(hop);
00419 if (!rd.isEmpty()) {
00420
00421 addRouter(rd);
00422 }
00423 }
00424 hop = (rd.isEmpty() ? hop : rd.name());
00425 }
00426 names << hop;
00427 }
00428 return Circuit(circ.id(), circ.status(), names);
00429 }
00430