Added own class for GxsNetTunnelsDialog

* Improved GXS Sync Tunnels display
* cleanup code
This commit is contained in:
defnax 2026-01-01 13:32:46 +01:00
parent 2e0112b730
commit 3380fccced
7 changed files with 636 additions and 225 deletions

View file

@ -0,0 +1,376 @@
/*******************************************************************************
* gui/statistics/GxsNetTunnelsDialog.cpp *
* *
* Copyright (c) 2025 Retroshare Team <retroshare.project@gmail.com> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
* *
*******************************************************************************/
#include "retroshare/rsconfig.h"
#include <retroshare/rsturtle.h>
#include <retroshare/rspeers.h>
#include <retroshare/rsgxstunnel.h>
#include <retroshare/rsservicecontrol.h>
#include <retroshare/rsidentity.h>
#include <retroshare/rsgxsdistsync.h>
#include "GxsNetTunnelsDialog.h"
#include <QObject>
#include <QModelIndex>
#include <QHeaderView>
#include <QPainter>
#include <QStylePainter>
#include <algorithm> // for sort
#include <time.h>
#include <util/rsprint.h>
#include "util/RsQtVersion.h"
#include "gui/settings/rsharesettings.h"
class NetTunnelsListDelegate: public QAbstractItemDelegate
{
public:
NetTunnelsListDelegate(QObject *parent=0);
virtual ~NetTunnelsListDelegate();
void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const;
QSize sizeHint(const QStyleOptionViewItem &, const QModelIndex &) const;
};
NetTunnelsListDelegate::NetTunnelsListDelegate(QObject *parent) : QAbstractItemDelegate(parent)
{
}
NetTunnelsListDelegate::~NetTunnelsListDelegate(void)
{
}
void NetTunnelsListDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const
{
QString strNA = tr("N/A");
QStyleOptionViewItem opt = option;
QString temp ;
float flValue;
qint64 qi64Value;
// prepare
painter->save();
painter->setClipRect(opt.rect);
//set text color
QVariant value = index.data(Qt::ForegroundRole);
if(value.isValid() && qvariant_cast<QColor>(value).isValid()) {
opt.palette.setColor(QPalette::Text, qvariant_cast<QColor>(value));
}
QPalette::ColorGroup cg = option.state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled;
if(option.state & QStyle::State_Selected){
painter->setPen(opt.palette.color(cg, QPalette::HighlightedText));
} else {
painter->setPen(opt.palette.color(cg, QPalette::Text));
}
// draw the background color
if(option.showDecorationSelected && (option.state & QStyle::State_Selected)) {
if(cg == QPalette::Normal && !(option.state & QStyle::State_Active)) {
cg = QPalette::Inactive;
}
painter->fillRect(option.rect, option.palette.brush(cg, QPalette::Highlight));
} else {
value = index.data(Qt::BackgroundRole);
if(value.isValid() && qvariant_cast<QColor>(value).isValid()) {
painter->fillRect(option.rect, qvariant_cast<QColor>(value));
}
}
switch(index.column()) {
case COLUMN_SERVICE :
painter->drawText(option.rect, Qt::AlignLeft, index.data().toString());
break;
case COLUMN_GROUPID:
painter->drawText(option.rect, Qt::AlignLeft, index.data().toString());
break;
case COLUMN_POLICY:
painter->drawText(option.rect, Qt::AlignLeft, index.data().toString());
break;
case COLUMN_STATUS:
painter->drawText(option.rect, Qt::AlignHCenter, index.data().toString());
break;
case COLUMN_LASTCONTACT:
painter->drawText(option.rect, Qt::AlignLeft, index.data().toString());
break;
default:
painter->drawText(option.rect, Qt::AlignLeft, index.data().toString());
}
// done
painter->restore();
}
QSize NetTunnelsListDelegate::sizeHint(const QStyleOptionViewItem & option/*option*/, const QModelIndex & index) const
{
float FS = QFontMetricsF(option.font).height();
//float fact = FS/14.0 ;
float w = QFontMetrics_horizontalAdvance(QFontMetricsF(option.font), index.data(Qt::DisplayRole).toString());
return QSize(w,FS*1.2);
//return QSize(50*fact,17*fact);
}
GxsNetTunnelsDialog::GxsNetTunnelsDialog(QWidget *parent)
: RsAutoUpdatePage(2000,parent)
{
setupUi(this) ;
m_ProcessSettings = false;
TunnelDelegate = new NetTunnelsListDelegate();
groups_treeWidget->setItemDelegate(TunnelDelegate);
float FS = QFontMetricsF(font()).height();
float fact = FS/14.0 ;
QHeaderView * _header = groups_treeWidget->header () ;
_header->resizeSection (COLUMN_SERVICE, 270*fact);
_header->resizeSection (COLUMN_GROUPID, 270*fact);
_header->resizeSection (COLUMN_STATUS, 140*fact);
// load settings
processSettings(true);
}
GxsNetTunnelsDialog::~GxsNetTunnelsDialog()
{
// save settings
processSettings(false);
}
void GxsNetTunnelsDialog::processSettings(bool bLoad)
{
m_ProcessSettings = true;
Settings->beginGroup(QString("GxsNetTunnelsDialog"));
if (bLoad) {
// load settings
// state of splitter
//splitter->restoreState(Settings->value("Splitter").toByteArray());
} else {
// save settings
// state of splitter
//Settings->setValue("Splitter", splitter->saveState());
}
Settings->endGroup();
m_ProcessSettings = false;
}
static QString getGroupStatusString(RsGxsNetTunnelGroupInfo::GroupStatus group_status)
{
switch(group_status)
{
default:
case RsGxsNetTunnelGroupInfo::RS_GXS_NET_TUNNEL_GRP_STATUS_UNKNOWN : return QObject::tr("Unknown") ;
case RsGxsNetTunnelGroupInfo::RS_GXS_NET_TUNNEL_GRP_STATUS_IDLE : return QObject::tr("Idle");
case RsGxsNetTunnelGroupInfo::RS_GXS_NET_TUNNEL_GRP_STATUS_VPIDS_AVAILABLE : return QObject::tr("Virtual peers available");
}
return QString();
}
static QString getGroupPolicyString(RsGxsNetTunnelGroupInfo::GroupPolicy group_policy)
{
switch(group_policy)
{
default:
case RsGxsNetTunnelGroupInfo::RS_GXS_NET_TUNNEL_GRP_POLICY_UNKNOWN : return QObject::tr("Unknown") ;
case RsGxsNetTunnelGroupInfo::RS_GXS_NET_TUNNEL_GRP_POLICY_PASSIVE : return QObject::tr("Passive") ;
case RsGxsNetTunnelGroupInfo::RS_GXS_NET_TUNNEL_GRP_POLICY_ACTIVE : return QObject::tr("Active") ;
case RsGxsNetTunnelGroupInfo::RS_GXS_NET_TUNNEL_GRP_POLICY_REQUESTING : return QObject::tr("Requesting peers") ;
}
return QString();
}
static QString getLastContactString(time_t last_contact)
{
time_t now = time(NULL);
if(last_contact == 0)
return QObject::tr("Never");
return QString::number(now - last_contact) + " secs ago" ;
}
static QString getServiceNameString(uint16_t service_id)
{
static RsPeerServiceInfo ownServices;
if(ownServices.mServiceList.find(service_id) == ownServices.mServiceList.end())
rsServiceControl->getOwnServices(ownServices);
return QString::fromUtf8(ownServices.mServiceList[RsServiceInfo::RsServiceInfoUIn16ToFullServiceId(service_id)].mServiceName.c_str()) ;
}
static QString getVirtualPeerStatusString(uint8_t status)
{
switch(status)
{
default:
case RsGxsNetTunnelVirtualPeerInfo::RS_GXS_NET_TUNNEL_VP_STATUS_UNKNOWN : return QObject::tr("Unknown") ;
case RsGxsNetTunnelVirtualPeerInfo::RS_GXS_NET_TUNNEL_VP_STATUS_TUNNEL_OK : return QObject::tr("Tunnel OK") ;
case RsGxsNetTunnelVirtualPeerInfo::RS_GXS_NET_TUNNEL_VP_STATUS_ACTIVE : return QObject::tr("Tunnel active") ;
}
return QString();
}
static QString getSideString(uint8_t side)
{
return side?QObject::tr("Client"):QObject::tr("Server") ;
}
static QString getMasterKeyString(const uint8_t *key,uint32_t size)
{
return QString::fromStdString(RsUtil::BinToHex(key,size,10));
}
void GxsNetTunnelsDialog::updateDisplay()
{
/* do nothing if locked, or not visible */
if (RsAutoUpdatePage::eventsLocked() == true)
{
return;
}
if (!rsConfig)
{
return;
}
updateTunnels();
}
void GxsNetTunnelsDialog::updateTunnels()
{
// RsGxsNetTunnelGroupInfo:
//
// enum GroupStatus {
// RS_GXS_NET_TUNNEL_GRP_STATUS_UNKNOWN = 0x00, // unknown status
// RS_GXS_NET_TUNNEL_GRP_STATUS_IDLE = 0x01, // no virtual peers requested, just waiting
// RS_GXS_NET_TUNNEL_GRP_STATUS_VPIDS_AVAILABLE = 0x02 // some virtual peers are available. Data can be read/written
// };
// enum GroupPolicy {
// RS_GXS_NET_TUNNEL_GRP_POLICY_UNKNOWN = 0x00, // nothing has been set
// RS_GXS_NET_TUNNEL_GRP_POLICY_PASSIVE = 0x01, // group is available for server side tunnels, but does not explicitely request tunnels
// RS_GXS_NET_TUNNEL_GRP_POLICY_ACTIVE = 0x02, // group will only explicitely request tunnels if none available
// RS_GXS_NET_TUNNEL_GRP_POLICY_REQUESTING = 0x03, // group explicitely requests tunnels
// };
//
// RsGxsNetTunnelGroupInfo() : group_policy(RS_GXS_NET_TUNNEL_GRP_POLICY_PASSIVE),group_status(RS_GXS_NET_TUNNEL_GRP_STATUS_IDLE),last_contact(0) {}
//
// GroupPolicy group_policy ;
// GroupStatus group_status ;
// time_t last_contact ;
// RsFileHash hash ;
// uint16_t service_id ;
// std::set<RsPeerId> virtual_peers ;
//
// struct RsGxsNetTunnelVirtualPeerInfo:
//
// enum { RS_GXS_NET_TUNNEL_VP_STATUS_UNKNOWN = 0x00, // unknown status.
// RS_GXS_NET_TUNNEL_VP_STATUS_TUNNEL_OK = 0x01, // tunnel has been established and we're waiting for virtual peer id
// RS_GXS_NET_TUNNEL_VP_STATUS_ACTIVE = 0x02 // virtual peer id is known. Data can transfer.
// };
//
// RsGxsNetTunnelVirtualPeerInfo() : vpid_status(RS_GXS_NET_TUNNEL_VP_STATUS_UNKNOWN), last_contact(0),side(0) { memset(encryption_master_key,0,32) ; }
// virtual ~RsGxsNetTunnelVirtualPeerInfo(){}
//
// uint8_t vpid_status ; // status of the peer
// time_t last_contact ; // last time some data was sent/recvd
// uint8_t side ; // client/server
// uint8_t encryption_master_key[32];
//
// RsPeerId turtle_virtual_peer_id ; // turtle peer to use when sending data to this vpid.
//
// RsGxsGroupId group_id ; // group that virtual peer is providing
// uint16_t service_id ; // this is used for checkng consistency of the incoming data
QTreeWidget *peerTreeWidget = groups_treeWidget;
// Clear existing items to prevent duplicates on refresh
peerTreeWidget->clear();
// Request info about ongoing tunnels
std::map<RsGxsGroupId, RsGxsNetTunnelGroupInfo> groups; // groups on the client and server side
std::map<TurtleVirtualPeerId, RsGxsNetTunnelVirtualPeerId> turtle2gxsnettunnel; // convertion table from turtle to net tunnel virtual peer id
std::map<RsGxsNetTunnelVirtualPeerId, RsGxsNetTunnelVirtualPeerInfo> virtual_peers; // current virtual peers, which group they provide, and how to talk to them through turtle
Bias20Bytes bias;
// Fetch data from rsGxsDistSync
if (rsGxsDistSync) {
rsGxsDistSync->getStatistics(groups, virtual_peers, turtle2gxsnettunnel, bias);
}
randombias->setText(tr("Random Bias: %1").arg(getMasterKeyString(bias.toByteArray(),20))) ;
peerTreeWidget->setSelectionMode(QAbstractItemView::SingleSelection);
for(auto it = groups.begin(); it != groups.end(); ++it)
{
// Create the Parent (Group) Item
QTreeWidgetItem *groups_item = new QTreeWidgetItem(peerTreeWidget);
groups_item->setExpanded(true); // This prevents it from "closing"
// Populate Group Data
groups_item->setData(COLUMN_SERVICE, Qt::DisplayRole, "0x" + QString::number(it->second.service_id, 16) + " (" + getServiceNameString(it->second.service_id) + ")");
groups_item->setData(COLUMN_GROUPID, Qt::DisplayRole, QString::fromStdString(it->first.toStdString()));
groups_item->setData(COLUMN_POLICY, Qt::DisplayRole, getGroupPolicyString(it->second.group_policy));
groups_item->setData(COLUMN_STATUS, Qt::DisplayRole, getGroupStatusString(it->second.group_status));
groups_item->setData(COLUMN_LASTCONTACT, Qt::DisplayRole, getLastContactString(it->second.last_contact));
// Iterate through Virtual Peers for this group
for(auto it2 = it->second.virtual_peers.begin(); it2 != it->second.virtual_peers.end(); ++it2)
{
auto it4 = turtle2gxsnettunnel.find(*it2);
QTreeWidgetItem *peers_item = new QTreeWidgetItem(groups_item); // Set parent immediately
if(it4 != turtle2gxsnettunnel.end())
{
auto it3 = virtual_peers.find(it4->second);
if(it3 != virtual_peers.end())
{
// Populate Peer Data
peers_item->setData(COLUMN_SERVICE, Qt::DisplayRole, QString::fromStdString((*it2).toStdString()));
peers_item->setData(COLUMN_GROUPID, Qt::DisplayRole, getMasterKeyString(it3->second.encryption_master_key, 32));
peers_item->setData(COLUMN_STATUS, Qt::DisplayRole, getVirtualPeerStatusString(it3->second.vpid_status) + " (" + getSideString(it3->second.side) + ")");
peers_item->setData(COLUMN_LASTCONTACT, Qt::DisplayRole, getLastContactString(it3->second.last_contact));
}
else
{
peers_item->setData(COLUMN_SERVICE, Qt::DisplayRole, QString::fromStdString((*it2).toStdString()) + " (No info)");
}
}
else
{
peers_item->setData(COLUMN_SERVICE, Qt::DisplayRole, QString::fromStdString((*it2).toStdString()) );
peers_item->setData(COLUMN_GROUPID, Qt::DisplayRole, tr(" (No Peer information available)"));
}
}
}
}

View file

@ -0,0 +1,63 @@
/*******************************************************************************
* gui/statistics/GxsNetTunnelsDialog.h *
* *
* Copyright (c) 2025 Retroshare Team <retroshare.project@gmail.com> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
* *
*******************************************************************************/
#pragma once
#include <QAbstractItemDelegate>
#include <retroshare/rsturtle.h>
#include <retroshare/rstypes.h>
#include <retroshare-gui/RsAutoUpdatePage.h>
#include "ui_GxsNetTunnelsDialog.h"
// Defines for download list list columns
#define COLUMN_SERVICE 0
#define COLUMN_GROUPID 1
#define COLUMN_POLICY 2
#define COLUMN_STATUS 3
#define COLUMN_LASTCONTACT 4
class QModelIndex;
class QPainter;
class NetTunnelsListDelegate ;
class GxsNetTunnelsDialog: public RsAutoUpdatePage, public Ui::GxsNetTunnelsDialog
{
Q_OBJECT
public:
GxsNetTunnelsDialog(QWidget *parent = NULL) ;
~GxsNetTunnelsDialog();
void updateTunnels();
public slots:
virtual void updateDisplay() ;
private:
void processSettings(bool bLoad);
bool m_ProcessSettings;
QTreeWidgetItem *peers_item ;
protected:
NetTunnelsListDelegate *TunnelDelegate;
} ;

View file

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>GxsNetTunnelsDialog</class>
<widget class="QWidget" name="GxsNetTunnelsDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>572</width>
<height>350</height>
</rect>
</property>
<property name="windowTitle">
<string>Router Statistics</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>GXS Groups</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QTreeWidget" name="groups_treeWidget">
<property name="sortingEnabled">
<bool>true</bool>
</property>
<property name="headerHidden">
<bool>false</bool>
</property>
<column>
<property name="text">
<string>Service</string>
</property>
</column>
<column>
<property name="text">
<string>Group ID / Master Key</string>
</property>
</column>
<column>
<property name="text">
<string>Policy</string>
</property>
</column>
<column>
<property name="text">
<string>Status</string>
</property>
</column>
<column>
<property name="text">
<string>Last contact</string>
</property>
</column>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="randombias">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -32,6 +32,7 @@
#include <algorithm> // for sort
#include <time.h>
#include "util/RsQtVersion.h"
#include "gui/settings/rsharesettings.h"
#define COL_ID 0
@ -46,6 +47,112 @@
static const uint MAX_TUNNEL_REQUESTS_DISPLAY = 10 ;
class FTTunnelsListDelegate: public QAbstractItemDelegate
{
public:
FTTunnelsListDelegate(QObject *parent=0);
virtual ~FTTunnelsListDelegate();
void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const;
QSize sizeHint(const QStyleOptionViewItem &, const QModelIndex &) const;
};
FTTunnelsListDelegate::FTTunnelsListDelegate(QObject *parent) : QAbstractItemDelegate(parent)
{
}
FTTunnelsListDelegate::~FTTunnelsListDelegate(void)
{
}
void FTTunnelsListDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const
{
QString strNA = tr("N/A");
QStyleOptionViewItem opt = option;
QString temp ;
float flValue;
qint64 qi64Value;
// prepare
painter->save();
painter->setClipRect(opt.rect);
//set text color
QVariant value = index.data(Qt::ForegroundRole);
if(value.isValid() && qvariant_cast<QColor>(value).isValid()) {
opt.palette.setColor(QPalette::Text, qvariant_cast<QColor>(value));
}
QPalette::ColorGroup cg = option.state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled;
if(option.state & QStyle::State_Selected){
painter->setPen(opt.palette.color(cg, QPalette::HighlightedText));
} else {
painter->setPen(opt.palette.color(cg, QPalette::Text));
}
// draw the background color
if(option.showDecorationSelected && (option.state & QStyle::State_Selected)) {
if(cg == QPalette::Normal && !(option.state & QStyle::State_Active)) {
cg = QPalette::Inactive;
}
painter->fillRect(option.rect, option.palette.brush(cg, QPalette::Highlight));
} else {
value = index.data(Qt::BackgroundRole);
if(value.isValid() && qvariant_cast<QColor>(value).isValid()) {
painter->fillRect(option.rect, qvariant_cast<QColor>(value));
}
}
switch(index.column()) {
/*case COLUMN_SERVICE :
//temp = QString::asprintf("%.3f ", index.data().toFloat());
//temp=QString::number(index.data().toFloat());
painter->drawText(option.rect, Qt::AlignLeft, index.data().toString());
break;
case COLUMN_GROUPID:
//temp = QString::asprintf("%.3f ", index.data().toFloat());
//temp=QString::number(index.data().toFloat());
painter->drawText(option.rect, Qt::AlignLeft, index.data().toString());
break;
case COLUMN_POLICY:
//temp=QString::number(index.data().toInt());
painter->drawText(option.rect, Qt::AlignLeft, index.data().toString());
break;
case COLUMN_STATUS:
/*flValue = index.data().toFloat();
if (flValue < std::numeric_limits<float>::max()){
temp = QString::asprintf("%.3f ", flValue);
} else {
temp=strNA;
}*/
/*painter->drawText(option.rect, Qt::AlignHCenter, index.data().toString());
break;
case COLUMN_LASTCONTACT:
/*qi64Value = index.data().value<qint64>();
if (qi64Value < std::numeric_limits<qint64>::max()){
temp= QString::number(qi64Value);
} else {
temp = strNA;
}*/
/*painter->drawText(option.rect, Qt::AlignHCenter, index.data().toString());
break;*/
default:
painter->drawText(option.rect, Qt::AlignLeft, index.data().toString());
}
// done
painter->restore();
}
QSize FTTunnelsListDelegate::sizeHint(const QStyleOptionViewItem & option/*option*/, const QModelIndex & index) const
{
float FS = QFontMetricsF(option.font).height();
//float fact = FS/14.0 ;
float w = QFontMetrics_horizontalAdvance(QFontMetricsF(option.font), index.data(Qt::DisplayRole).toString());
return QSize(w,FS*1.2);
//return QSize(50*fact,17*fact);
}
TurtleRouterDialog::TurtleRouterDialog(QWidget *parent)
: RsAutoUpdatePage(2000,parent)
@ -59,6 +166,10 @@ TurtleRouterDialog::TurtleRouterDialog(QWidget *parent)
QStringList stl ;
int n=0 ;
FTTDelegate = new FTTunnelsListDelegate();
_f2f_TW->setItemDelegate(FTTDelegate);
tunnels_treeWidget->setItemDelegate(FTTDelegate);
stl.clear() ;
stl.push_back(tr("Search requests")) ;
top_level_s_requests = new QTreeWidgetItem(_f2f_TW,stl) ;
@ -174,6 +285,9 @@ void TurtleRouterDialog::updateTunnelRequests( const std::vector<std::vector<std
delete taken ;
}
_f2f_TW->setSelectionMode(QAbstractItemView::SingleSelection);
tunnels_treeWidget->setSelectionMode(QAbstractItemView::SingleSelection);
for(uint i=0;i<hashes_info.size();++i)
findParentHashItem(hashes_info[i][0]) ;
@ -197,12 +311,6 @@ void TurtleRouterDialog::updateTunnelRequests( const std::vector<std::vector<std
num /= 1024.0f,++k;
sprintf(tmp,"%3.2f %s",num,units[k].c_str()) ;
//QString str = tr("Tunnel id") + ": " + QString::fromUtf8(tunnels_info[i][0].c_str()) + "\t" + tr("Speed") + ": " + QString::fromStdString(tmp) + "\t " + tr("last transfer") + ": " + QString::fromStdString(tunnels_info[i][4])+ "\t" + QString::fromUtf8(tunnels_info[i][2].c_str()) + " -> " + QString::fromUtf8(tunnels_info[i][1].c_str());
//stl.clear() ;
//stl.push_back(str) ;
//QTreeWidgetItem *item = new QTreeWidgetItem(stl);
//parent->addChild(item);
QTreeWidgetItem *tunnel_item = NULL;
tunnel_item = new QTreeWidgetItem();
@ -231,11 +339,7 @@ void TurtleRouterDialog::updateTunnelRequests( const std::vector<std::vector<std
for(uint i=0;i<search_reqs_info.size();++i)
{
//QString str = tr("Request id: %1\t %3 secs ago\t from %2\t %4 (%5 hits)").arg(search_reqs_info[i].request_id,0,16).arg(getPeerName(search_reqs_info[i].source_peer_id), -25).arg(search_reqs_info[i].age).arg(QString::fromUtf8(search_reqs_info[i].keywords.c_str(),search_reqs_info[i].keywords.length())).arg(QString::number(search_reqs_info[i].hits));
//stl.clear() ;
//stl.push_back(str) ;
QTreeWidgetItem *sr_item = NULL;
sr_item = new QTreeWidgetItem();
top_level_s_requests->addChild(sr_item) ;
@ -245,17 +349,12 @@ void TurtleRouterDialog::updateTunnelRequests( const std::vector<std::vector<std
sr_item->setData(COL_TIME, Qt::DisplayRole, QString::number(search_reqs_info[i].age) + " secs ago");
sr_item->setData(COL_STRING, Qt::DisplayRole, QString::fromUtf8(search_reqs_info[i].keywords.c_str()) + QString::number(search_reqs_info[i].keywords.length()) + " (" + QString::number(search_reqs_info[i].hits) + " hits)");
//top_level_s_requests->addChild(new QTreeWidgetItem(stl)) ;
}
top_level_s_requests->setText(0, tr("Search requests") + " (" + QString::number(search_reqs_info.size()) + ")" ) ;
for(uint i=0;i<tunnel_reqs_info.size();++i)
if(i+MAX_TUNNEL_REQUESTS_DISPLAY >= tunnel_reqs_info.size() || i < MAX_TUNNEL_REQUESTS_DISPLAY)
{
//QString str = tr("Request id: %1\t from [%2]\t %3 secs ago").arg(tunnel_reqs_info[i].request_id,0,16).arg(getPeerName(tunnel_reqs_info[i].source_peer_id)).arg(tunnel_reqs_info[i].age);
//stl.clear() ;
//stl.push_back(str) ;
/* find the entry */
QTreeWidgetItem *tunnelr_item = NULL;
tunnelr_item = new QTreeWidgetItem();
@ -264,8 +363,6 @@ void TurtleRouterDialog::updateTunnelRequests( const std::vector<std::vector<std
tunnelr_item->setData(COL_ID, Qt::DisplayRole, QString::number(tunnel_reqs_info[i].request_id));
tunnelr_item->setData(COL_FROM, Qt::DisplayRole, getPeerName(tunnel_reqs_info[i].source_peer_id) ) ;
tunnelr_item->setData(COL_TIME, Qt::DisplayRole, QString::number(tunnel_reqs_info[i].age) + " secs ago");
//top_level_t_requests->addChild(new QTreeWidgetItem(stl)) ;
}
else if(i == MAX_TUNNEL_REQUESTS_DISPLAY)
{
@ -495,198 +592,3 @@ void GxsAuthenticatedTunnelsDialog::updateDisplay()
pixmap = tmppixmap;
maxHeight = std::max(oy,10*celly);
}
//=======================================================================================================================//
GxsNetTunnelsDialog::GxsNetTunnelsDialog(QWidget *parent)
: TunnelStatisticsDialog(parent)
{
}
static QString getGroupStatusString(RsGxsNetTunnelGroupInfo::GroupStatus group_status)
{
switch(group_status)
{
default:
case RsGxsNetTunnelGroupInfo::RS_GXS_NET_TUNNEL_GRP_STATUS_UNKNOWN : return QObject::tr("Unknown") ;
case RsGxsNetTunnelGroupInfo::RS_GXS_NET_TUNNEL_GRP_STATUS_IDLE : return QObject::tr("Idle");
case RsGxsNetTunnelGroupInfo::RS_GXS_NET_TUNNEL_GRP_STATUS_VPIDS_AVAILABLE : return QObject::tr("Virtual peers available");
}
return QString();
}
static QString getGroupPolicyString(RsGxsNetTunnelGroupInfo::GroupPolicy group_policy)
{
switch(group_policy)
{
default:
case RsGxsNetTunnelGroupInfo::RS_GXS_NET_TUNNEL_GRP_POLICY_UNKNOWN : return QObject::tr("Unknown") ;
case RsGxsNetTunnelGroupInfo::RS_GXS_NET_TUNNEL_GRP_POLICY_PASSIVE : return QObject::tr("Passive") ;
case RsGxsNetTunnelGroupInfo::RS_GXS_NET_TUNNEL_GRP_POLICY_ACTIVE : return QObject::tr("Active") ;
case RsGxsNetTunnelGroupInfo::RS_GXS_NET_TUNNEL_GRP_POLICY_REQUESTING : return QObject::tr("Requesting peers") ;
}
return QString();
}
static QString getLastContactString(time_t last_contact)
{
time_t now = time(NULL);
if(last_contact == 0)
return QObject::tr("Never");
return QString::number(now - last_contact) + " secs ago" ;
}
static QString getServiceNameString(uint16_t service_id)
{
static RsPeerServiceInfo ownServices;
if(ownServices.mServiceList.find(service_id) == ownServices.mServiceList.end())
rsServiceControl->getOwnServices(ownServices);
return QString::fromUtf8(ownServices.mServiceList[RsServiceInfo::RsServiceInfoUIn16ToFullServiceId(service_id)].mServiceName.c_str()) ;
}
static QString getVirtualPeerStatusString(uint8_t status)
{
switch(status)
{
default:
case RsGxsNetTunnelVirtualPeerInfo::RS_GXS_NET_TUNNEL_VP_STATUS_UNKNOWN : return QObject::tr("Unknown") ;
case RsGxsNetTunnelVirtualPeerInfo::RS_GXS_NET_TUNNEL_VP_STATUS_TUNNEL_OK : return QObject::tr("Tunnel OK") ;
case RsGxsNetTunnelVirtualPeerInfo::RS_GXS_NET_TUNNEL_VP_STATUS_ACTIVE : return QObject::tr("Tunnel active") ;
}
return QString();
}
static QString getSideString(uint8_t side)
{
return side?QObject::tr("Client"):QObject::tr("Server") ;
}
static QString getMasterKeyString(const uint8_t *key,uint32_t size)
{
return QString::fromStdString(RsUtil::BinToHex(key,size,10));
}
void GxsNetTunnelsDialog::updateDisplay()
{
// Request info about ongoing tunnels
std::map<RsGxsGroupId,RsGxsNetTunnelGroupInfo> groups; // groups on the client and server side
std::map<TurtleVirtualPeerId,RsGxsNetTunnelVirtualPeerId> turtle2gxsnettunnel; // convertion table from turtle to net tunnel virtual peer id
std::map<RsGxsNetTunnelVirtualPeerId, RsGxsNetTunnelVirtualPeerInfo> virtual_peers; // current virtual peers, which group they provide, and how to talk to them through turtle
Bias20Bytes bias;
rsGxsDistSync->getStatistics(groups,virtual_peers,turtle2gxsnettunnel,bias) ;
// RsGxsNetTunnelGroupInfo:
//
// enum GroupStatus {
// RS_GXS_NET_TUNNEL_GRP_STATUS_UNKNOWN = 0x00, // unknown status
// RS_GXS_NET_TUNNEL_GRP_STATUS_IDLE = 0x01, // no virtual peers requested, just waiting
// RS_GXS_NET_TUNNEL_GRP_STATUS_VPIDS_AVAILABLE = 0x02 // some virtual peers are available. Data can be read/written
// };
// enum GroupPolicy {
// RS_GXS_NET_TUNNEL_GRP_POLICY_UNKNOWN = 0x00, // nothing has been set
// RS_GXS_NET_TUNNEL_GRP_POLICY_PASSIVE = 0x01, // group is available for server side tunnels, but does not explicitely request tunnels
// RS_GXS_NET_TUNNEL_GRP_POLICY_ACTIVE = 0x02, // group will only explicitely request tunnels if none available
// RS_GXS_NET_TUNNEL_GRP_POLICY_REQUESTING = 0x03, // group explicitely requests tunnels
// };
//
// RsGxsNetTunnelGroupInfo() : group_policy(RS_GXS_NET_TUNNEL_GRP_POLICY_PASSIVE),group_status(RS_GXS_NET_TUNNEL_GRP_STATUS_IDLE),last_contact(0) {}
//
// GroupPolicy group_policy ;
// GroupStatus group_status ;
// time_t last_contact ;
// RsFileHash hash ;
// uint16_t service_id ;
// std::set<RsPeerId> virtual_peers ;
//
// struct RsGxsNetTunnelVirtualPeerInfo:
//
// enum { RS_GXS_NET_TUNNEL_VP_STATUS_UNKNOWN = 0x00, // unknown status.
// RS_GXS_NET_TUNNEL_VP_STATUS_TUNNEL_OK = 0x01, // tunnel has been established and we're waiting for virtual peer id
// RS_GXS_NET_TUNNEL_VP_STATUS_ACTIVE = 0x02 // virtual peer id is known. Data can transfer.
// };
//
// RsGxsNetTunnelVirtualPeerInfo() : vpid_status(RS_GXS_NET_TUNNEL_VP_STATUS_UNKNOWN), last_contact(0),side(0) { memset(encryption_master_key,0,32) ; }
// virtual ~RsGxsNetTunnelVirtualPeerInfo(){}
//
// uint8_t vpid_status ; // status of the peer
// time_t last_contact ; // last time some data was sent/recvd
// uint8_t side ; // client/server
// uint8_t encryption_master_key[32];
//
// RsPeerId turtle_virtual_peer_id ; // turtle peer to use when sending data to this vpid.
//
// RsGxsGroupId group_id ; // group that virtual peer is providing
// uint16_t service_id ; // this is used for checkng consistency of the incoming data
// update the pixmap
//
// now draw the shit
QPixmap tmppixmap(maxWidth, maxHeight);
tmppixmap.fill(Qt::transparent);
//setFixedHeight(maxHeight);
QPainter painter(&tmppixmap);
painter.begin(this);
// extracts the height of the fonts in pixels. This is used to calibrate the size of the objects to draw.
float fontHeight = QFontMetricsF(font()).height();
float fact = fontHeight/14.0;
int cellx = 6*fact ;
int celly = (10+4)*fact ;
int ox=5*fact,oy=5*fact ;
painter.setPen(QColor::fromRgb(0,0,0)) ;
painter.drawText(ox+2*cellx,oy+celly,tr("Random Bias: %1").arg(getMasterKeyString(bias.toByteArray(),20))) ; oy += celly ;
painter.drawText(ox+2*cellx,oy+celly,tr("GXS Groups:")) ; oy += celly ;
for(auto it(groups.begin());it!=groups.end();++it)
{
painter.drawText(ox+4*cellx,oy+celly,tr("Service: %1 (%2) - Group ID: %3,\t policy: %4, \tstatus: %5, \tlast contact: %6")
.arg("0x" + QString::number(it->second.service_id, 16))
.arg(getServiceNameString(it->second.service_id))
.arg(QString::fromStdString(it->first.toStdString()))
.arg(getGroupPolicyString(it->second.group_policy))
.arg(getGroupStatusString(it->second.group_status))
.arg(getLastContactString(it->second.last_contact))
),oy+=celly ;
for(auto it2(it->second.virtual_peers.begin());it2!=it->second.virtual_peers.end();++it2)
{
auto it4 = turtle2gxsnettunnel.find(*it2) ;
if(it4 != turtle2gxsnettunnel.end())
{
auto it3 = virtual_peers.find(it4->second) ;
if(virtual_peers.end() != it3)
painter.drawText(ox+6*cellx,oy+celly,tr("Peer: %1:\tstatus: %2/%3, \tlast contact: %4, \tMaster key: %5.")
.arg(QString::fromStdString((*it2).toStdString()))
.arg(getVirtualPeerStatusString(it3->second.vpid_status))
.arg(getSideString(it3->second.side))
.arg(getLastContactString(it3->second.last_contact))
.arg(getMasterKeyString(it3->second.encryption_master_key,32))
),oy+=celly ;
}
else
painter.drawText(ox+6*cellx,oy+celly,tr("Peer: %1: no information available")
.arg(QString::fromStdString((*it2).toStdString()))
),oy+=celly;
}
}
oy += celly ;
pixmap = tmppixmap;
maxHeight = std::max(oy,10*celly);
}

View file

@ -28,6 +28,9 @@
#include "ui_TurtleRouterDialog.h"
#include "ui_TurtleRouterStatistics.h"
class QModelIndex;
class QPainter;
class FTTunnelsListDelegate ;
class TurtleRouterDialog: public RsAutoUpdatePage, public Ui::TurtleRouterDialogForm
{
@ -57,6 +60,9 @@ class TurtleRouterDialog: public RsAutoUpdatePage, public Ui::TurtleRouterDialog
QTreeWidgetItem *top_level_s_requests ;
QTreeWidgetItem *top_level_t_requests ;
protected:
FTTunnelsListDelegate *FTTDelegate;
} ;
class TunnelStatisticsDialog: public RsAutoUpdatePage
@ -99,15 +105,3 @@ public:
private:
virtual void updateDisplay() ;
} ;
class GxsNetTunnelsDialog: public TunnelStatisticsDialog
{
Q_OBJECT
public:
GxsNetTunnelsDialog(QWidget *parent = NULL) ;
~GxsNetTunnelsDialog() {}
private:
virtual void updateDisplay() ;
} ;

View file

@ -29,6 +29,7 @@
#include <retroshare/rspeers.h>
#include "TurtleRouterStatistics.h"
#include "TurtleRouterDialog.h"
#include "GxsNetTunnelsDialog.h"
#include "gui/settings/rsharesettings.h"

View file

@ -418,6 +418,7 @@ HEADERS += rshare.h \
gui/statistics/DhtWindow.h \
gui/statistics/GlobalRouterStatistics.h \
gui/statistics/GxsTransportStatistics.h \
gui/statistics/GxsNetTunnelsDialog.h \
gui/statistics/StatisticsWindow.h \
gui/statistics/BwCtrlWindow.h \
gui/statistics/RttStatistics.h \
@ -723,6 +724,7 @@ FORMS += gui/StartDialog.ui \
gui/statistics/GxsIdStatistics.ui \
gui/statistics/GlobalRouterStatistics.ui \
gui/statistics/GxsTransportStatistics.ui \
gui/statistics/GxsNetTunnelsDialog.ui \
gui/statistics/StatisticsWindow.ui \
gui/statistics/BwCtrlWindow.ui \
gui/statistics/RttStatistics.ui \
@ -974,6 +976,7 @@ SOURCES += main.cpp \
gui/statistics/GxsIdStatistics.cpp \
gui/statistics/GlobalRouterStatistics.cpp \
gui/statistics/GxsTransportStatistics.cpp \
gui/statistics/GxsNetTunnelsDialog.cpp \
gui/statistics/StatisticsWindow.cpp \
gui/statistics/BwCtrlWindow.cpp \
gui/statistics/RttStatistics.cpp \