* Split PeerNetQt into a MainWindow and a DhtWindow.

* Added DHT query display.
 * Added "keepalive" messages so TOU connections never timeout.



git-svn-id: http://svn.code.sf.net/p/retroshare/code/branches/v0.5-peernet@4304 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
drbob 2011-06-20 09:52:31 +00:00
parent d5e61e042c
commit 2abd787af1
10 changed files with 462 additions and 161 deletions

View File

@ -17,14 +17,17 @@ QT += network xml script
SOURCES += main.cpp\
mainwindow.cpp \
dhtwindow.cpp \
peernet.cc \
netstatebox.cc
HEADERS += mainwindow.h \
dhtwindow.h \
peernet.h \
netstatebox.h
FORMS += mainwindow.ui
FORMS += mainwindow.ui \
dhtwindow.ui
librs {

191
PeerNetQt/src/dhtwindow.cpp Normal file
View File

@ -0,0 +1,191 @@
#include "dhtwindow.h"
#include "ui_dhtwindow.h"
#include <QTimer>
#include <QDateTime>
#include <sstream>
#include <algorithm>
#include <iostream>
#include <iomanip>
DhtWindow::DhtWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::DhtWindow)
{
ui->setupUi(this);
// tick for gui update.
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(update()));
timer->start(1000);
// connect add Peer button.
//connect(ui->addButton, SIGNAL(clicked()), this, SLOT(addPeer()));
//connect(ui->chatLineEdit, SIGNAL(returnPressed()), this, SLOT(sendChat()));
}
DhtWindow::~DhtWindow()
{
delete ui;
}
void DhtWindow::changeEvent(QEvent *e)
{
QMainWindow::changeEvent(e);
switch (e->type()) {
case QEvent::LanguageChange:
ui->retranslateUi(this);
break;
default:
break;
}
}
void DhtWindow::setPeerNet(PeerNet *pnet)
{
mPeerNet = pnet;
}
void DhtWindow::update()
{
//std::cerr << "DhtWindow::update()" << std::endl;
updateDhtPeers();
updateDhtQueries();
}
#define DTW_COL_BUCKET 0
#define DTW_COL_IPADDR 1
#define DTW_COL_PEERID 2
#define DTW_COL_FLAGS 3
#define DTW_COL_FOUND 4
#define DTW_COL_SEND 5
#define DTW_COL_RECV 6
void DhtWindow::updateDhtPeers()
{
/* Hackish display of all Dht peers, should be split into buckets (as children) */
bdNodeId ownId;
mPeerNet->getOwnId(&ownId);
QString status = QString::fromStdString(mPeerNet->getDhtStatusString());
ui->dhtLabel->setText(status);
std::list<bdPeer> allpeers;
std::list<bdPeer>::iterator it;
int i;
for(i = 0; i < 160; i++)
{
bdBucket peers;
mPeerNet->get_dht_peers(i, peers);
for(it = peers.entries.begin(); it != peers.entries.end(); it++)
{
allpeers.push_back(*it);
}
}
QTreeWidget *dhtTreeWidget = ui->dhtTreeWidget;
dhtTreeWidget->clear();
time_t now = time(NULL);
for(it = allpeers.begin(); it != allpeers.end(); it++)
{
/* find the entry */
QTreeWidgetItem *dht_item = NULL;
/* insert */
dht_item = new QTreeWidgetItem();
int dist = bdStdBucketDistance(&ownId, &(it->mPeerId.id));
std::ostringstream buckstr;
buckstr << dist;
std::ostringstream ipstr;
ipstr << inet_ntoa(it->mPeerId.addr.sin_addr);
ipstr << ":" << ntohs(it->mPeerId.addr.sin_port);
std::ostringstream idstr;
bdStdPrintNodeId(idstr, &(it->mPeerId.id));
std::ostringstream flagsstr;
flagsstr << "0x" << std::hex << std::setfill('0') << it->mPeerFlags;
std::ostringstream foundstr;
foundstr << now - it->mFoundTime << " secs ago";
std::ostringstream lastsendstr;
lastsendstr << now - it->mLastSendTime << " secs ago";
std::ostringstream lastrecvstr;
lastrecvstr << now - it->mLastRecvTime << " secs ago";
dht_item -> setData(DTW_COL_BUCKET, Qt::DisplayRole, QString::fromStdString(buckstr.str()));
dht_item -> setData(DTW_COL_IPADDR, Qt::DisplayRole, QString::fromStdString(ipstr.str()));
dht_item -> setData(DTW_COL_PEERID, Qt::DisplayRole, QString::fromStdString(idstr.str()));
dht_item -> setData(DTW_COL_FLAGS, Qt::DisplayRole, QString::fromStdString(flagsstr.str()));
dht_item -> setData(DTW_COL_FOUND, Qt::DisplayRole, QString::fromStdString(foundstr.str()));
dht_item -> setData(DTW_COL_SEND, Qt::DisplayRole, QString::fromStdString(lastsendstr.str()));
dht_item -> setData(DTW_COL_RECV, Qt::DisplayRole, QString::fromStdString(lastrecvstr.str()));
dhtTreeWidget->addTopLevelItem(dht_item);
}
}
#define QTW_COL_PEERID 0
#define QTW_COL_STATUS 1
#define QTW_COL_FLAGS 2
#define QTW_COL_RESULTS 3
void DhtWindow::updateDhtQueries()
{
std::list<bdId>::iterator lit;
std::map<bdNodeId, bdQueryStatus> queries;
std::map<bdNodeId, bdQueryStatus>::iterator it;
mPeerNet->get_dht_queries(queries);
QTreeWidget *queryTreeWidget = ui->queryTreeWidget;
queryTreeWidget->clear();
time_t now = time(NULL);
for(it = queries.begin(); it != queries.end(); it++)
{
/* find the entry */
QTreeWidgetItem *item = NULL;
/* insert */
item = new QTreeWidgetItem();
std::ostringstream statusstr;
statusstr << (it->second).mStatus;
std::ostringstream resultsstr;
for(lit = (it->second).mResults.begin(); lit != (it->second).mResults.end(); lit++)
{
resultsstr << "[" << inet_ntoa(lit->addr.sin_addr) << ":" << htons(lit->addr.sin_port) << "] ";
}
std::ostringstream idstr;
bdStdPrintNodeId(idstr, &(it->first));
std::ostringstream flagsstr;
flagsstr << "0x" << std::hex << std::setfill('0') << it->second.mQFlags;
item -> setData(QTW_COL_PEERID, Qt::DisplayRole, QString::fromStdString(idstr.str()));
item -> setData(QTW_COL_STATUS, Qt::DisplayRole, QString::fromStdString(statusstr.str()));
item -> setData(QTW_COL_FLAGS, Qt::DisplayRole, QString::fromStdString(flagsstr.str()));
item -> setData(QTW_COL_RESULTS, Qt::DisplayRole, QString::fromStdString(resultsstr.str()));
queryTreeWidget->addTopLevelItem(item);
}
}

33
PeerNetQt/src/dhtwindow.h Normal file
View File

@ -0,0 +1,33 @@
#ifndef DHTWINDOW_H
#define DHTWINDOW_H
#include <QMainWindow>
#include "peernet.h"
namespace Ui {
class DhtWindow;
}
class DhtWindow : public QMainWindow {
Q_OBJECT
public:
DhtWindow(QWidget *parent = 0);
~DhtWindow();
void setPeerNet(PeerNet *pnet);
void updateDhtPeers();
void updateDhtQueries();
public slots:
void update();
protected:
void changeEvent(QEvent *e);
private:
Ui::DhtWindow *ui;
PeerNet *mPeerNet;
};
#endif // DHTWINDOW_H

145
PeerNetQt/src/dhtwindow.ui Normal file
View File

@ -0,0 +1,145 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DhtWindow</class>
<widget class="QMainWindow" name="DhtWindow">
<property name="enabled">
<bool>true</bool>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>644</width>
<height>590</height>
</rect>
</property>
<property name="windowTitle">
<string>PeerNetQt: Dht Summary</string>
</property>
<widget class="QWidget" name="centralWidget">
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QLabel" name="dhtLabel">
<property name="text">
<string>DHT Details:</string>
</property>
</widget>
</item>
<item>
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QWidget" name="layoutWidget">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Dht Queries</string>
</property>
</widget>
</item>
<item>
<widget class="QTreeWidget" name="queryTreeWidget">
<column>
<property name="text">
<string>PeerId</string>
</property>
</column>
<column>
<property name="text">
<string>Status</string>
</property>
</column>
<column>
<property name="text">
<string>Flags</string>
</property>
</column>
<column>
<property name="text">
<string>Results</string>
</property>
</column>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="layoutWidget">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Dht Bucket Entries</string>
</property>
</widget>
</item>
<item>
<widget class="QTreeWidget" name="dhtTreeWidget">
<column>
<property name="text">
<string>Bucket</string>
</property>
</column>
<column>
<property name="text">
<string>Ip:Port</string>
</property>
</column>
<column>
<property name="text">
<string>Key</string>
</property>
</column>
<column>
<property name="text">
<string>StatusFlags</string>
</property>
</column>
<column>
<property name="text">
<string>Found</string>
</property>
</column>
<column>
<property name="text">
<string>Last Send</string>
</property>
</column>
<column>
<property name="text">
<string>Last Recv</string>
</property>
</column>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>644</width>
<height>22</height>
</rect>
</property>
</widget>
<widget class="QToolBar" name="mainToolBar">
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
</widget>
<widget class="QStatusBar" name="statusBar"/>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>

View File

@ -4,6 +4,7 @@
#include <stdio.h>
#include <QtGui/QApplication>
#include "mainwindow.h"
#include "dhtwindow.h"
int main(int argc, char *argv[])
{
@ -106,8 +107,12 @@ int main(int argc, char *argv[])
QApplication a(argc, argv);
MainWindow w;
w.show();
DhtWindow dw;
dw.hide();
w.setPeerNet(pnet);
w.setDhtWindow(&dw);
dw.setPeerNet(pnet);
return a.exec();
}

View File

@ -21,6 +21,7 @@ MainWindow::MainWindow(QWidget *parent) :
// connect add Peer button.
connect(ui->addButton, SIGNAL(clicked()), this, SLOT(addPeer()));
connect(ui->dhtButton, SIGNAL(clicked()), this, SLOT(showDhtWindow()));
connect(ui->chatLineEdit, SIGNAL(returnPressed()), this, SLOT(sendChat()));
}
@ -47,11 +48,20 @@ void MainWindow::setPeerNet(PeerNet *pnet)
}
void MainWindow::setDhtWindow(DhtWindow *dw)
{
mDhtWindow = dw;
}
void MainWindow::showDhtWindow()
{
mDhtWindow->show();
}
void MainWindow::update()
{
//std::cerr << "MainWindow::update()" << std::endl;
updateNetStatus();
updateDhtPeers();
updateNetPeers();
updateChat();
@ -205,109 +215,6 @@ void MainWindow::updateNetStatus()
}
#define DTW_COL_BUCKET 0
#define DTW_COL_IPADDR 1
#define DTW_COL_PEERID 2
#define DTW_COL_FLAGS 3
#define DTW_COL_FOUND 4
#define DTW_COL_SEND 5
#define DTW_COL_RECV 6
void MainWindow::updateDhtPeers()
{
/* Hackish display of all Dht peers, should be split into buckets (as children) */
bdNodeId ownId;
mPeerNet->getOwnId(&ownId);
QString status = QString::fromStdString(mPeerNet->getDhtStatusString());
ui->dhtLabel->setText(status);
std::list<bdPeer> allpeers;
std::list<bdPeer>::iterator it;
int i;
for(i = 0; i < 160; i++)
{
bdBucket peers;
mPeerNet->get_dht_peers(i, peers);
for(it = peers.entries.begin(); it != peers.entries.end(); it++)
{
allpeers.push_back(*it);
}
}
QTreeWidget *dhtTreeWidget = ui->dhtTreeWidget;
dhtTreeWidget->clear();
#if 0
/* clear old entries */
int itemCount = dhtTreeWidget->topLevelItemCount();
for (int nIndex = 0; nIndex < itemCount;)
{
QTreeWidgetItem *tmp_item = dhtTreeWidget->topLevelItem(nIndex);
std::string tmpid = tmp_item->data(DTW_COL_PEERID, Qt::DisplayRole).toString().toStdString();
if (peerIds.end() == std::find(peerIds.begin(), peerIds.end(), tmpid))
{
peerTreeWidget->removeItemWidget(tmp_item, 0);
/* remove it! */
itemCount--;
}
else
{
nIndex++;
}
}
#endif
time_t now = time(NULL);
for(it = allpeers.begin(); it != allpeers.end(); it++)
{
/* find the entry */
QTreeWidgetItem *dht_item = NULL;
/* insert */
dht_item = new QTreeWidgetItem();
int dist = bdStdBucketDistance(&ownId, &(it->mPeerId.id));
std::ostringstream buckstr;
buckstr << dist;
std::ostringstream ipstr;
ipstr << inet_ntoa(it->mPeerId.addr.sin_addr);
ipstr << ":" << ntohs(it->mPeerId.addr.sin_port);
std::ostringstream idstr;
bdStdPrintNodeId(idstr, &(it->mPeerId.id));
std::ostringstream flagsstr;
flagsstr << "0x" << std::hex << std::setfill('0') << it->mPeerFlags;
std::ostringstream foundstr;
foundstr << now - it->mFoundTime << " secs ago";
std::ostringstream lastsendstr;
lastsendstr << now - it->mLastSendTime << " secs ago";
std::ostringstream lastrecvstr;
lastrecvstr << now - it->mLastRecvTime << " secs ago";
dht_item -> setData(DTW_COL_BUCKET, Qt::DisplayRole, QString::fromStdString(buckstr.str()));
dht_item -> setData(DTW_COL_IPADDR, Qt::DisplayRole, QString::fromStdString(ipstr.str()));
dht_item -> setData(DTW_COL_PEERID, Qt::DisplayRole, QString::fromStdString(idstr.str()));
dht_item -> setData(DTW_COL_FLAGS, Qt::DisplayRole, QString::fromStdString(flagsstr.str()));
dht_item -> setData(DTW_COL_FOUND, Qt::DisplayRole, QString::fromStdString(foundstr.str()));
dht_item -> setData(DTW_COL_SEND, Qt::DisplayRole, QString::fromStdString(lastsendstr.str()));
dht_item -> setData(DTW_COL_RECV, Qt::DisplayRole, QString::fromStdString(lastrecvstr.str()));
dhtTreeWidget->addTopLevelItem(dht_item);
}
}
void MainWindow::updateNetPeers()
{

View File

@ -4,6 +4,8 @@
#include <QMainWindow>
#include "peernet.h"
#include "DhtWindow.h"
namespace Ui {
class MainWindow;
}
@ -15,9 +17,9 @@ public:
~MainWindow();
void setPeerNet(PeerNet *pnet);
void setDhtWindow(DhtWindow *dw);
void updateNetStatus();
void updateDhtPeers();
void updateNetPeers();
void updateChat();
void addChatMsg(std::string id, std::string msg);
@ -26,6 +28,7 @@ public slots:
void update();
void addPeer();
void sendChat();
void showDhtWindow();
protected:
void changeEvent(QEvent *e);
@ -33,6 +36,7 @@ protected:
private:
Ui::MainWindow *ui;
PeerNet *mPeerNet;
DhtWindow *mDhtWindow;
};
#endif // MAINWINDOW_H

View File

@ -14,7 +14,7 @@
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
<string>PeerNetQt</string>
</property>
<widget class="QWidget" name="centralWidget">
<layout class="QVBoxLayout" name="verticalLayout_4">
@ -36,6 +36,13 @@
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="dhtButton">
<property name="text">
<string>Dht Info</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="netStatusLabel">
<property name="text">
@ -112,7 +119,7 @@
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QWidget" name="">
<widget class="QWidget" name="layoutWidget">
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>0</number>
@ -203,56 +210,6 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="layoutWidget">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="dhtLabel">
<property name="text">
<string>DHT Details:</string>
</property>
</widget>
</item>
<item>
<widget class="QTreeWidget" name="dhtTreeWidget">
<column>
<property name="text">
<string>Bucket</string>
</property>
</column>
<column>
<property name="text">
<string>Ip:Port</string>
</property>
</column>
<column>
<property name="text">
<string>Key</string>
</property>
</column>
<column>
<property name="text">
<string>StatusFlags</string>
</property>
</column>
<column>
<property name="text">
<string>Found</string>
</property>
</column>
<column>
<property name="text">
<string>Last Send</string>
</property>
</column>
<column>
<property name="text">
<string>Last Recv</string>
</property>
</column>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>

View File

@ -505,6 +505,23 @@ int PeerNet::get_failedpeer_status(std::string id, PeerStatus &status)
return 0;
}
int PeerNet::get_dht_queries(std::map<bdNodeId, bdQueryStatus> &queries)
{
return mUdpBitDht->getDhtQueries(queries);
}
int PeerNet::get_query_status(std::string id, bdQuerySummary &query)
{
bdNodeId tmpId;
if (!bdStdLoadNodeId(&tmpId, id))
{
return 0;
}
return mUdpBitDht->getDhtQueryStatus(&tmpId, query);
}
/* remember peers */
int PeerNet::storePeers(std::string filepath)
{
@ -1178,6 +1195,8 @@ int PeerNet::tick()
minuteTick();
keepaliveConnections();
return 1;
}
@ -1719,10 +1738,36 @@ void PeerNet::monitorConnections()
int read = tou_read(fd, buf, 10240);
if (read > 0)
{
it->second.mPeerIncoming += std::string(buf);
std::cerr << "PeerNet::monitorConnections() Read from Connection: " << it->second.mId;
std::string msg(buf);
std::cerr << "TS: " << time(NULL) << " From: " << it->second.mId;
std::cerr << " RawMsg: " << msg;
std::cerr << std::endl;
#if 1
for(int i = 0; i < msg.size(); )
{
if (msg[i] == '^')
{
msg.erase(i,1);
}
else
{
i++;
}
}
#endif
if (msg.size() > 0)
{
//std::cerr << "PeerNet::monitorConnections() Read from Connection: " << it->second.mId;
//std::cerr << std::endl;
//std::cerr << "PeerNet::monitorConnections() CleanedMsg: " << msg;
//std::cerr << std::endl;
std::cerr << "TS: " << time(NULL) << " From: " << it->second.mId;
std::cerr << " RawMsg: " << msg;
std::cerr << std::endl;
it->second.mPeerIncoming += msg;
}
}
}
else
@ -1797,4 +1842,10 @@ int PeerNet::getMessage(std::string id, std::string &msg)
void PeerNet::keepaliveConnections()
{
std::string msg("^");
sendMessage(msg);
}

View File

@ -122,8 +122,12 @@ class PeerNet: public BitDhtCallback
std::string getPeerStatusString();
std::string getPeerAddressString();
std::string getDhtStatusString();
int get_dht_queries(std::map<bdNodeId, bdQueryStatus> &queries);
int get_query_status(std::string id, bdQuerySummary &query);
int get_dht_peers(int lvl, bdBucket &peers);
//int get_dht_peers(int lvl, std::list<DhtPeer> &peers);
int get_net_peers(std::list<std::string> &peerIds);
int get_peer_status(std::string peerId, PeerStatus &status);
@ -165,6 +169,7 @@ int UnreachablePeerCallback_locked(const bdId *id,
/**** Connection Handling ******/
void monitorConnections();
void keepaliveConnections();
int removeRelayConnection(const bdId *srcId, const bdId *destId);
int installRelayConnection(const bdId *srcId, const bdId *destId);