#include #include #include #include #include #include #include #include #include "TurtleRouterDialog.h" #include #include #include // for sort #include #include "gui/settings/rsharesettings.h" static const uint MAX_TUNNEL_REQUESTS_DISPLAY = 10 ; TurtleRouterDialog::TurtleRouterDialog(QWidget *parent) : RsAutoUpdatePage(2000,parent) { setupUi(this) ; m_bProcessSettings = false; // Init the basic setup. // QStringList stl ; int n=0 ; stl.clear() ; stl.push_back(tr("Search requests")) ; top_level_s_requests = new QTreeWidgetItem(_f2f_TW,stl) ; _f2f_TW->insertTopLevelItem(n++,top_level_s_requests) ; stl.clear() ; stl.push_back(tr("Tunnel requests")) ; top_level_t_requests = new QTreeWidgetItem(_f2f_TW,stl) ; _f2f_TW->insertTopLevelItem(n++,top_level_t_requests) ; top_level_hashes.clear() ; // load settings processSettings(true); } TurtleRouterDialog::~TurtleRouterDialog() { // save settings processSettings(false); } void TurtleRouterDialog::processSettings(bool bLoad) { m_bProcessSettings = true; Settings->beginGroup(QString("TurtleRouterDialog")); 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_bProcessSettings = false; } bool sr_Compare( TurtleSearchRequestDisplayInfo m1, TurtleSearchRequestDisplayInfo m2) { return m1.age < m2.age; } void TurtleRouterDialog::updateDisplay() { std::vector > hashes_info ; std::vector > tunnels_info ; std::vector search_reqs_info ; std::vector tunnel_reqs_info ; rsTurtle->getInfo(hashes_info,tunnels_info,search_reqs_info,tunnel_reqs_info) ; std::sort(search_reqs_info.begin(),search_reqs_info.end(),sr_Compare) ; updateTunnelRequests(hashes_info,tunnels_info,search_reqs_info,tunnel_reqs_info) ; } QString TurtleRouterDialog::getPeerName(const RsPeerId& peer_id) { static std::map names ; std::map::const_iterator it = names.find(peer_id) ; if( it != names.end()) return it->second ; else { RsPeerDetails detail ; if(!rsPeers->getPeerDetails(peer_id,detail)) return "unknown peer"; return (names[peer_id] = QString::fromUtf8(detail.name.c_str())) ; } } void TurtleRouterDialog::updateTunnelRequests( const std::vector >& hashes_info, const std::vector >& tunnels_info, const std::vector& search_reqs_info, const std::vector& tunnel_reqs_info) { // now display this in the QTableWidgets QStringList stl ; // remove all children of top level objects for(int i=0;i<_f2f_TW->topLevelItemCount();++i) { QTreeWidgetItem *taken ; while( (taken = _f2f_TW->topLevelItem(i)->takeChild(0)) != NULL) delete taken ; } for(uint i=0;itext(0).left(14) == tr("Unknown hashes")) unknown_hash_found = true ; float num = strtof(tunnels_info[i][5].c_str(), NULL); // printFloatNumber char tmp[100] ; std::string units[4] = { "B/s","KB/s","MB/s","GB/s" } ; int k=0 ; while(num >= 800.0f && k<4) 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); QFont font = item->font(0); if(strtol(tunnels_info[i][4].c_str(), NULL, 0)>10) // stuck { font.setItalic(true); item->setFont(0,font); } if(strtof(tunnels_info[i][5].c_str(), NULL)>1000) // fast { font.setBold(true); item->setFont(0,font); } } for(uint i=0;iaddChild(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 < 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) ; top_level_t_requests->addChild(new QTreeWidgetItem(stl)) ; } else if(i == MAX_TUNNEL_REQUESTS_DISPLAY) { stl.clear() ; stl.push_back(QString("...")) ; top_level_t_requests->addChild(new QTreeWidgetItem(stl)) ; } top_level_t_requests->setText(0, tr("Tunnel requests") + " ("+QString::number(tunnel_reqs_info.size()) + ")") ; QTreeWidgetItem *unknown_hashs_item = findParentHashItem(RsFileHash().toStdString()) ; unknown_hashs_item->setText(0,tr("Unknown hashes") + " (" + QString::number(unknown_hashs_item->childCount())+QString(")")) ; // Ok, this is a N2 search, but there are very few elements in the list. for(int i=2;i<_f2f_TW->topLevelItemCount();) { bool found = false ; if(_f2f_TW->topLevelItem(i)->text(0).left(14) == tr("Unknown hashes") && unknown_hash_found) found = true ; if(_f2f_TW->topLevelItem(i)->childCount() > 0) // this saves uploading hashes found = true ; for(uint j=0;jtopLevelItem(i)->text(0).toStdString() == hashes_info[j][0]) found=true ; if(!found) delete _f2f_TW->takeTopLevelItem(i) ; else ++i ; } } QTreeWidgetItem *TurtleRouterDialog::findParentHashItem(const std::string& hash) { static const std::string null_hash = RsFileHash().toStdString() ; // look for the hash, and insert a new element if necessary. // QList items = _f2f_TW->findItems((hash==null_hash)?tr("Unknown hashes"):QString::fromStdString(hash),Qt::MatchStartsWith) ; if(items.empty()) { QStringList stl ; stl.push_back((hash==null_hash)?tr("Unknown hashes"):QString::fromStdString(hash)) ; QTreeWidgetItem *item = new QTreeWidgetItem(_f2f_TW,stl) ; _f2f_TW->insertTopLevelItem(0,item) ; return item ; } else return items.front() ; } //=======================================================================================================================// TunnelStatisticsDialog::TunnelStatisticsDialog(QWidget *parent) : RsAutoUpdatePage(2000,parent) { m_bProcessSettings = false; maxWidth = 200 ; maxHeight = 200 ; // load settings processSettings(true); } TunnelStatisticsDialog::~TunnelStatisticsDialog() { // save settings processSettings(false); } void TunnelStatisticsDialog::processSettings(bool bLoad) { m_bProcessSettings = true; Settings->beginGroup(QString("TurtleRouterStatistics")); if (bLoad) { // load settings } else { // save settings } Settings->endGroup(); m_bProcessSettings = false; } QString TunnelStatisticsDialog::getPeerName(const RsPeerId &peer_id) { static std::map names ; std::map::const_iterator it = names.find(peer_id) ; if( it != names.end()) return it->second ; else { RsPeerDetails detail ; if(!rsPeers->getPeerDetails(peer_id,detail)) return tr("Unknown Peer"); return (names[peer_id] = QString::fromUtf8(detail.name.c_str())) ; } } QString TunnelStatisticsDialog::getPeerName(const RsGxsId& gxs_id) { static std::map names ; std::map::const_iterator it = names.find(gxs_id) ; if( it != names.end()) return it->second ; else { RsIdentityDetails detail ; if(!rsIdentity->getIdDetails(gxs_id,detail)) return tr("Unknown Peer"); return (names[gxs_id] = QString::fromUtf8(detail.mNickname.c_str())) ; } } QString TunnelStatisticsDialog::speedString(float f) { if(f < 1.0f) return QString("0 B/s") ; if(f < 1024.0f) return QString::number((int)f)+" B/s" ; return QString::number(f/1024.0,'f',2) + " KB/s"; } void TunnelStatisticsDialog::paintEvent(QPaintEvent */*event*/) { QStylePainter(this).drawPixmap(0, 0, pixmap); } void TunnelStatisticsDialog::resizeEvent(QResizeEvent *event) { QRect TaskGraphRect = geometry(); maxWidth = TaskGraphRect.width(); maxHeight = TaskGraphRect.height() ; QWidget::resizeEvent(event); update(); } //=======================================================================================================================// GxsAuthenticatedTunnelsDialog::GxsAuthenticatedTunnelsDialog(QWidget *parent) : TunnelStatisticsDialog(parent) { } void GxsAuthenticatedTunnelsDialog::updateDisplay() { // Request info about ongoing tunnels std::vector tunnel_infos ; rsGxsTunnel->getTunnelsInfo(tunnel_infos) ; // // Tunnel information // // GxsTunnelId tunnel_id ; // GXS Id we're talking to // RsGxsId destination_gxs_id ; // GXS Id we're talking to // RsGxsId source_gxs_id ; // GXS Id we're using to talk // uint32_t tunnel_status ; // active, requested, DH pending, etc. // uint32_t total_size_sent ; // total bytes sent through that tunnel since openned (including management). // uint32_t total_size_received ; // total bytes received through that tunnel since openned (including management). // // Data packets // uint32_t pending_data_packets; // number of packets not acknowledged by other side, still on their way. Should be 0 unless something bad happens. // uint32_t total_data_packets_sent ; // total number of data packets sent (does not include tunnel management) // uint32_t total_data_packets_received ; // total number of data packets received (does not include tunnel management) // now draw the shit QPixmap tmppixmap(maxWidth, maxHeight); tmppixmap.fill(Qt::transparent); //setFixedHeight(maxHeight); QPainter painter(&tmppixmap); painter.initFrom(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; //maxHeight = 500*fact ; 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("Authenticated tunnels:")) ; oy += celly ; for(uint32_t i=0;igetOwnServices(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 groups; // groups on the client and server side std::map turtle2gxsnettunnel; // convertion table from turtle to net tunnel virtual peer id std::map 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 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.initFrom(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); }