From 641b38690c6f77cb2e2be8e25dc78c581ab40327 Mon Sep 17 00:00:00 2001 From: Christophe Dumez Date: Sun, 17 Apr 2011 14:42:38 +0000 Subject: [PATCH] Added uTP support --- Changelog | 1 + src/preferences/advancedsettings.h | 9 +--- src/preferences/options.ui | 65 ++++++++++++++++++++--- src/preferences/options_imp.cpp | 34 ++++++++++++ src/preferences/options_imp.h | 1 + src/preferences/preferences.h | 21 +++++++- src/properties/peerlistdelegate.h | 28 +++++----- src/properties/peerlistwidget.cpp | 83 +++++++++++++++++++----------- src/properties/peerlistwidget.h | 3 ++ src/qtlibtorrent/qbtsession.cpp | 28 ++++++++++ 10 files changed, 216 insertions(+), 57 deletions(-) diff --git a/Changelog b/Changelog index 184468e6d..364a84cd3 100644 --- a/Changelog +++ b/Changelog @@ -1,4 +1,5 @@ * Unreleased - Christophe Dumez - v2.8.0 + - FEATURE: Added full libtorrent v0.16 support (uTP, ...) - FEATURE: Added support for secure SMTP connection (SSL) - FEATURE: Added support for SMTP authentication - FEATURE: Added UPnP/NAT-PMP port forward for the Web UI port diff --git a/src/preferences/advancedsettings.h b/src/preferences/advancedsettings.h index c8152fb3a..d092cfbb2 100644 --- a/src/preferences/advancedsettings.h +++ b/src/preferences/advancedsettings.h @@ -13,7 +13,7 @@ #include "preferences.h" enum AdvSettingsCols {PROPERTY, VALUE}; -enum AdvSettingsRows {DISK_CACHE, OUTGOING_PORT_MIN, OUTGOING_PORT_MAX, IGNORE_LIMIT_LAN, COUNT_OVERHEAD, RECHECK_COMPLETED, LIST_REFRESH, RESOLVE_COUNTRIES, RESOLVE_HOSTS, MAX_HALF_OPEN, SUPER_SEEDING, NETWORK_IFACE, NETWORK_ADDRESS, PROGRAM_NOTIFICATIONS, TRACKER_STATUS, TRACKER_PORT, +enum AdvSettingsRows {DISK_CACHE, OUTGOING_PORT_MIN, OUTGOING_PORT_MAX, IGNORE_LIMIT_LAN, RECHECK_COMPLETED, LIST_REFRESH, RESOLVE_COUNTRIES, RESOLVE_HOSTS, MAX_HALF_OPEN, SUPER_SEEDING, NETWORK_IFACE, NETWORK_ADDRESS, PROGRAM_NOTIFICATIONS, TRACKER_STATUS, TRACKER_PORT, #if defined(Q_WS_WIN) || defined(Q_WS_MAC) UPDATE_CHECK, #endif @@ -28,7 +28,7 @@ class AdvancedSettings: public QTableWidget { private: QSpinBox spin_cache, outgoing_ports_min, outgoing_ports_max, spin_list_refresh, spin_maxhalfopen, spin_tracker_port; - QCheckBox cb_ignore_limits_lan, cb_count_overhead, cb_recheck_completed, cb_resolve_countries, cb_resolve_hosts, + QCheckBox cb_ignore_limits_lan, cb_recheck_completed, cb_resolve_countries, cb_resolve_hosts, cb_super_seeding, cb_program_notifications, cb_tracker_status, cb_confirm_torrent_deletion; QComboBox combo_iface; #if defined(Q_WS_WIN) || defined(Q_WS_MAC) @@ -69,8 +69,6 @@ public slots: pref.setOutgoingPortsMax(outgoing_ports_max.value()); // Ignore limits on LAN pref.ignoreLimitsOnLAN(cb_ignore_limits_lan.isChecked()); - // Include protocol overhead in transfer limits - pref.includeOverheadInLimits(cb_count_overhead.isChecked()); // Recheck torrents on completion pref.recheckTorrentsOnCompletion(cb_recheck_completed.isChecked()); // Transfer list refresh interval @@ -170,9 +168,6 @@ private slots: // Ignore transfer limits on local network cb_ignore_limits_lan.setChecked(pref.ignoreLimitsOnLAN()); setRow(IGNORE_LIMIT_LAN, tr("Ignore transfer limits on local network"), &cb_ignore_limits_lan); - // Consider protocol overhead in transfer limits - cb_count_overhead.setChecked(pref.includeOverheadInLimits()); - setRow(COUNT_OVERHEAD, tr("Include TCP/IP overhead in transfer limits"), &cb_count_overhead); // Recheck completed torrents cb_recheck_completed.setChecked(pref.recheckTorrentsOnCompletion()); setRow(RECHECK_COMPLETED, tr("Recheck torrents on completion"), &cb_recheck_completed); diff --git a/src/preferences/options.ui b/src/preferences/options.ui index 206557de6..d91ba3fa8 100644 --- a/src/preferences/options.ui +++ b/src/preferences/options.ui @@ -1405,16 +1405,16 @@ QGroupBox { 0 - 0 - 504 - 384 + -16 + 489 + 425 - Global Speed Limits + Global Rate Limits @@ -1513,13 +1513,66 @@ QGroupBox { + + + + Options + + + + + + + + Protocol: + + + + + + + + TCP and uTP + + + + + TCP only + + + + + uTP only + + + + + + + + + + Apply rate limit to uTP connections + + + + + + + Apply rate limit to transport overhead + + + + + + - Alternative Global Speed Limits + Alternative Global Rate Limits @@ -1625,7 +1678,7 @@ QGroupBox { - Schedule the use of alternative speed limits + Schedule the use of alternative rate limits true diff --git a/src/preferences/options_imp.cpp b/src/preferences/options_imp.cpp index 17949152d..af88df152 100644 --- a/src/preferences/options_imp.cpp +++ b/src/preferences/options_imp.cpp @@ -113,6 +113,8 @@ options_imp::options_imp(QWidget *parent): comboTrayIcon->setVisible(false); #endif // Connect signals / slots + // Speeds + connect(comboBTProtocol, SIGNAL(currentIndexChanged(int)), SLOT(updateBTProtocolSettings(int))); // Proxy tab connect(comboProxyType, SIGNAL(currentIndexChanged(int)),this, SLOT(enableProxy(int))); @@ -168,6 +170,9 @@ options_imp::options_imp(QWidget *parent): connect(schedule_from, SIGNAL(timeChanged(QTime)), this, SLOT(enableApplyButton())); connect(schedule_to, SIGNAL(timeChanged(QTime)), this, SLOT(enableApplyButton())); connect(schedule_days, SIGNAL(currentIndexChanged(int)), this, SLOT(enableApplyButton())); + connect(comboBTProtocol, SIGNAL(currentIndexChanged(int)), SLOT(enableApplyButton())); + connect(checkLimituTPConnections, SIGNAL(toggled(bool)), SLOT(enableApplyButton())); + connect(checkLimitTransportOverhead, SIGNAL(toggled(bool)), SLOT(enableApplyButton())); // Bittorrent tab connect(checkMaxConnecs, SIGNAL(toggled(bool)), this, SLOT(enableApplyButton())); connect(checkMaxConnecsPerTorrent, SIGNAL(toggled(bool)), this, SLOT(enableApplyButton())); @@ -216,6 +221,10 @@ options_imp::options_imp(QWidget *parent): connect(tabSelection, SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)), this, SLOT(changePage(QListWidgetItem *, QListWidgetItem*))); #if LIBTORRENT_VERSION_MINOR < 15 checkAppendqB->setVisible(false); +#endif +#if LIBTORRENT_VERSION_MINOR < 16 + comboBTProtocol->setVisible(false); + checkLimituTPConnections->setVisible(false); #endif // Load Advanced settings QVBoxLayout *adv_layout = new QVBoxLayout(); @@ -382,6 +391,9 @@ void options_imp::saveOptions(){ const QPair down_up_limit = getGlobalBandwidthLimits(); pref.setGlobalDownloadLimit(down_up_limit.first); pref.setGlobalUploadLimit(down_up_limit.second); + pref.setBTProtocol(comboBTProtocol->currentIndex()); + pref.setuTPRateLimited(checkLimituTPConnections->isChecked()); + pref.includeOverheadInLimits(checkLimitTransportOverhead->isChecked()); pref.setAltGlobalDownloadLimit(spinDownloadLimitAlt->value()); pref.setAltGlobalUploadLimit(spinUploadLimitAlt->value()); pref.setSchedulerEnabled(check_schedule->isChecked()); @@ -573,6 +585,10 @@ void options_imp::loadOptions(){ } spinUploadLimitAlt->setValue(pref.getAltGlobalUploadLimit()); spinDownloadLimitAlt->setValue(pref.getAltGlobalDownloadLimit()); + // Options + comboBTProtocol->setCurrentIndex((int)pref.getBTProtocol()); + checkLimituTPConnections->setChecked(pref.isuTPRateLimited()); + checkLimitTransportOverhead->setChecked(pref.includeOverheadInLimits()); // Scheduler check_schedule->setChecked(pref.isSchedulerEnabled()); schedule_from->setTime(pref.getSchedulerStartTime()); @@ -1188,3 +1204,21 @@ QString options_imp::languageToLocalizedString(QLocale::Language language, const } } } + +void options_imp::updateBTProtocolSettings(int protocol) +{ + switch(protocol) { + case BT::TCP: + checkLimituTPConnections->setEnabled(false); + break; + case BT::TCP_uTP: + checkLimituTPConnections->setEnabled(true); + break; + case BT::uTP: + checkLimituTPConnections->setEnabled(true); + break; + default: + Q_ASSERT(0); + break; + } +} diff --git a/src/preferences/options_imp.h b/src/preferences/options_imp.h index 3dc28962d..abf6b85bf 100644 --- a/src/preferences/options_imp.h +++ b/src/preferences/options_imp.h @@ -82,6 +82,7 @@ private slots: void on_removeScanFolderButton_clicked(); void on_registerDNSBtn_clicked(); void setLocale(const QString &locale); + void updateBTProtocolSettings(int protocol); private: // Methods diff --git a/src/preferences/preferences.h b/src/preferences/preferences.h index 419d72f18..71dabe954 100644 --- a/src/preferences/preferences.h +++ b/src/preferences/preferences.h @@ -62,7 +62,10 @@ namespace TrayIcon { enum Style { NORMAL = 0, MONO_DARK, MONO_LIGHT }; } namespace DNS { - enum Service { DYNDNS, NOIP }; +enum Service { DYNDNS, NOIP }; +} +namespace BT { +enum Protocol { TCP_uTP, TCP, uTP }; } class Preferences : public QIniSettings { @@ -537,6 +540,22 @@ public: setValue(QString::fromUtf8("Preferences/Bittorrent/MaxUploadsPerTorrent"), val); } + BT::Protocol getBTProtocol() const { + return (BT::Protocol)value(QString::fromUtf8("Preferences/Bittorrent/Protocol"), BT::TCP_uTP).toInt(); + } + + void setBTProtocol(int protocol) { + setValue("Preferences/Bittorrent/Protocol", protocol); + } + + bool isuTPRateLimited() const { + return value(QString::fromUtf8("Preferences/Bittorrent/uTP_rate_limiting"), false).toBool(); + } + + void setuTPRateLimited(bool enabled) { + setValue("Preferences/Bittorrent/uTP_rate_limiting", enabled); + } + bool isDHTEnabled() const { return value(QString::fromUtf8("Preferences/Bittorrent/DHT"), true).toBool(); } diff --git a/src/properties/peerlistdelegate.h b/src/properties/peerlistdelegate.h index e817f9383..e48931a90 100644 --- a/src/properties/peerlistdelegate.h +++ b/src/properties/peerlistdelegate.h @@ -35,11 +35,13 @@ #include #include "misc.h" -enum PeerListColumns {IP, CLIENT, PROGRESS, DOWN_SPEED, UP_SPEED, TOT_DOWN, TOT_UP, IP_HIDDEN}; - class PeerListDelegate: public QItemDelegate { Q_OBJECT +public: + enum PeerListColumns {IP, CONNECTION, CLIENT, PROGRESS, DOWN_SPEED, UP_SPEED, + TOT_DOWN, TOT_UP, IP_HIDDEN, COL_COUNT}; + public: PeerListDelegate(QObject *parent) : QItemDelegate(parent){} @@ -56,18 +58,18 @@ public: break; case DOWN_SPEED: case UP_SPEED:{ - QItemDelegate::drawBackground(painter, opt, index); - qreal speed = index.data().toDouble(); - if (speed > 0.0) - QItemDelegate::drawDisplay(painter, opt, opt.rect, misc::friendlyUnit(speed)+tr("/s", "/second (i.e. per second)")); - break; - } + QItemDelegate::drawBackground(painter, opt, index); + qreal speed = index.data().toDouble(); + if (speed > 0.0) + QItemDelegate::drawDisplay(painter, opt, opt.rect, misc::friendlyUnit(speed)+tr("/s", "/second (i.e. per second)")); + break; + } case PROGRESS:{ - QItemDelegate::drawBackground(painter, opt, index); - qreal progress = index.data().toDouble(); - QItemDelegate::drawDisplay(painter, opt, opt.rect, QString::number(progress*100., 'f', 1)+"%"); - break; - } + QItemDelegate::drawBackground(painter, opt, index); + qreal progress = index.data().toDouble(); + QItemDelegate::drawDisplay(painter, opt, opt.rect, QString::number(progress*100., 'f', 1)+"%"); + break; + } default: QItemDelegate::paint(painter, option, index); } diff --git a/src/properties/peerlistwidget.cpp b/src/properties/peerlistwidget.cpp index 97f7ec33d..c5e8426f4 100644 --- a/src/properties/peerlistwidget.cpp +++ b/src/properties/peerlistwidget.cpp @@ -57,20 +57,21 @@ PeerListWidget::PeerListWidget(PropertiesWidget *parent): QTreeView(parent), pro setAllColumnsShowFocus(true); setSelectionMode(QAbstractItemView::ExtendedSelection); // List Model - listModel = new QStandardItemModel(0, 8); - listModel->setHeaderData(IP, Qt::Horizontal, tr("IP")); - listModel->setHeaderData(CLIENT, Qt::Horizontal, tr("Client", "i.e.: Client application")); - listModel->setHeaderData(PROGRESS, Qt::Horizontal, tr("Progress", "i.e: % downloaded")); - listModel->setHeaderData(DOWN_SPEED, Qt::Horizontal, tr("Down Speed", "i.e: Download speed")); - listModel->setHeaderData(UP_SPEED, Qt::Horizontal, tr("Up Speed", "i.e: Upload speed")); - listModel->setHeaderData(TOT_DOWN, Qt::Horizontal, tr("Downloaded", "i.e: total data downloaded")); - listModel->setHeaderData(TOT_UP, Qt::Horizontal, tr("Uploaded", "i.e: total data uploaded")); + listModel = new QStandardItemModel(0, PeerListDelegate::COL_COUNT); + listModel->setHeaderData(PeerListDelegate::IP, Qt::Horizontal, tr("IP")); + listModel->setHeaderData(PeerListDelegate::CONNECTION, Qt::Horizontal, tr("Connection")); + listModel->setHeaderData(PeerListDelegate::CLIENT, Qt::Horizontal, tr("Client", "i.e.: Client application")); + listModel->setHeaderData(PeerListDelegate::PROGRESS, Qt::Horizontal, tr("Progress", "i.e: % downloaded")); + listModel->setHeaderData(PeerListDelegate::DOWN_SPEED, Qt::Horizontal, tr("Down Speed", "i.e: Download speed")); + listModel->setHeaderData(PeerListDelegate::UP_SPEED, Qt::Horizontal, tr("Up Speed", "i.e: Upload speed")); + listModel->setHeaderData(PeerListDelegate::TOT_DOWN, Qt::Horizontal, tr("Downloaded", "i.e: total data downloaded")); + listModel->setHeaderData(PeerListDelegate::TOT_UP, Qt::Horizontal, tr("Uploaded", "i.e: total data uploaded")); // Proxy model to support sorting without actually altering the underlying model proxyModel = new QSortFilterProxyModel(); proxyModel->setDynamicSortFilter(true); proxyModel->setSourceModel(listModel); setModel(proxyModel); - hideColumn(IP_HIDDEN); + hideColumn(PeerListDelegate::IP_HIDDEN); // Context menu setContextMenuPolicy(Qt::CustomContextMenu); connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showPeerListMenu(QPoint))); @@ -129,7 +130,7 @@ void PeerListWidget::showPeerListMenu(QPoint) { QStringList selectedPeerIPs; foreach(const QModelIndex &index, selectedIndexes) { int row = proxyModel->mapToSource(index).row(); - QString myip = listModel->data(listModel->index(row, IP_HIDDEN)).toString(); + QString myip = listModel->data(listModel->index(row, PeerListDelegate::IP_HIDDEN)).toString(); selectedPeerIPs << myip; } // Add Peer Action @@ -320,30 +321,31 @@ QStandardItem* PeerListWidget::addPeer(QString ip, peer_info peer) { host = resolver->getHostFromCache(peer.ip); } if(host.isNull()) - listModel->setData(listModel->index(row, IP), ip); + listModel->setData(listModel->index(row, PeerListDelegate::IP), ip); else - listModel->setData(listModel->index(row, IP), host); - listModel->setData(listModel->index(row, IP_HIDDEN), ip); + listModel->setData(listModel->index(row, PeerListDelegate::IP), host); + listModel->setData(listModel->index(row, PeerListDelegate::IP_HIDDEN), ip); // Resolve peer host name is asked if(resolver && host.isNull()) resolver->resolve(peer.ip); if(display_flags) { const QIcon ico = GeoIPManager::CountryISOCodeToIcon(peer.country); if(!ico.isNull()) { - listModel->setData(listModel->index(row, IP), ico, Qt::DecorationRole); + listModel->setData(listModel->index(row, PeerListDelegate::IP), ico, Qt::DecorationRole); const QString country_name = GeoIPManager::CountryISOCodeToName(peer.country); - listModel->setData(listModel->index(row, IP), country_name, Qt::ToolTipRole); + listModel->setData(listModel->index(row, PeerListDelegate::IP), country_name, Qt::ToolTipRole); } else { missingFlags.insert(ip); } } - listModel->setData(listModel->index(row, CLIENT), misc::toQStringU(peer.client)); - listModel->setData(listModel->index(row, PROGRESS), peer.progress); - listModel->setData(listModel->index(row, DOWN_SPEED), peer.payload_down_speed); - listModel->setData(listModel->index(row, UP_SPEED), peer.payload_up_speed); - listModel->setData(listModel->index(row, TOT_DOWN), (qulonglong)peer.total_download); - listModel->setData(listModel->index(row, TOT_UP), (qulonglong)peer.total_upload); - return listModel->item(row, IP); + listModel->setData(listModel->index(row, PeerListDelegate::CONNECTION), getConnectionString(peer.connection_type)); + listModel->setData(listModel->index(row, PeerListDelegate::CLIENT), misc::toQStringU(peer.client)); + listModel->setData(listModel->index(row, PeerListDelegate::PROGRESS), peer.progress); + listModel->setData(listModel->index(row, PeerListDelegate::DOWN_SPEED), peer.payload_down_speed); + listModel->setData(listModel->index(row, PeerListDelegate::UP_SPEED), peer.payload_up_speed); + listModel->setData(listModel->index(row, PeerListDelegate::TOT_DOWN), (qulonglong)peer.total_download); + listModel->setData(listModel->index(row, PeerListDelegate::TOT_UP), (qulonglong)peer.total_upload); + return listModel->item(row, PeerListDelegate::IP); } void PeerListWidget::updatePeer(QString ip, peer_info peer) { @@ -352,18 +354,19 @@ void PeerListWidget::updatePeer(QString ip, peer_info peer) { if(display_flags) { const QIcon ico = GeoIPManager::CountryISOCodeToIcon(peer.country); if(!ico.isNull()) { - listModel->setData(listModel->index(row, IP), ico, Qt::DecorationRole); + listModel->setData(listModel->index(row, PeerListDelegate::IP), ico, Qt::DecorationRole); const QString country_name = GeoIPManager::CountryISOCodeToName(peer.country); - listModel->setData(listModel->index(row, IP), country_name, Qt::ToolTipRole); + listModel->setData(listModel->index(row, PeerListDelegate::IP), country_name, Qt::ToolTipRole); missingFlags.remove(ip); } } - listModel->setData(listModel->index(row, CLIENT), misc::toQStringU(peer.client)); - listModel->setData(listModel->index(row, PROGRESS), peer.progress); - listModel->setData(listModel->index(row, DOWN_SPEED), peer.payload_down_speed); - listModel->setData(listModel->index(row, UP_SPEED), peer.payload_up_speed); - listModel->setData(listModel->index(row, TOT_DOWN), (qulonglong)peer.total_download); - listModel->setData(listModel->index(row, TOT_UP), (qulonglong)peer.total_upload); + listModel->setData(listModel->index(row, PeerListDelegate::CONNECTION), getConnectionString(peer.connection_type)); + listModel->setData(listModel->index(row, PeerListDelegate::CLIENT), misc::toQStringU(peer.client)); + listModel->setData(listModel->index(row, PeerListDelegate::PROGRESS), peer.progress); + listModel->setData(listModel->index(row, PeerListDelegate::DOWN_SPEED), peer.payload_down_speed); + listModel->setData(listModel->index(row, PeerListDelegate::UP_SPEED), peer.payload_up_speed); + listModel->setData(listModel->index(row, PeerListDelegate::TOT_DOWN), (qulonglong)peer.total_download); + listModel->setData(listModel->index(row, PeerListDelegate::TOT_UP), (qulonglong)peer.total_upload); } void PeerListWidget::handleResolved(const QString &ip, const QString &hostname) { @@ -384,3 +387,23 @@ void PeerListWidget::handleSortColumnChanged(int col) proxyModel->setSortRole(Qt::DisplayRole); } } + +QString PeerListWidget::getConnectionString(int connection_type) +{ + QString connection; + switch(connection_type) { +#if LIBTORRENT_VERSION_MINOR > 15 + case peer_info::bittorrent_utp: + connection = "uTP"; + break; + case peer_info::http_seed: +#endif + case peer_info::web_seed: + connection = "Web"; + break; + default: + connection = "BT"; + break; + } + return connection; +} diff --git a/src/properties/peerlistwidget.h b/src/properties/peerlistwidget.h index 511699cf7..66a3b1417 100644 --- a/src/properties/peerlistwidget.h +++ b/src/properties/peerlistwidget.h @@ -82,6 +82,9 @@ protected slots: void banSelectedPeers(QStringList peer_ips); void handleSortColumnChanged(int col); +private: + static QString getConnectionString(int connection_type); + private: QStandardItemModel *listModel; PeerListDelegate *listDelegate; diff --git a/src/qtlibtorrent/qbtsession.cpp b/src/qtlibtorrent/qbtsession.cpp index 383019ac0..51110e77e 100644 --- a/src/qtlibtorrent/qbtsession.cpp +++ b/src/qtlibtorrent/qbtsession.cpp @@ -453,6 +453,34 @@ void QBtSession::configureSession() { s->set_max_half_open_connections(pref.getMaxHalfOpenConnections()); // * Max connections limit setMaxConnections(pref.getMaxConnecs()); +#endif +#if LIBTORRENT_VERSION_MINOR > 15 + // uTP + switch((int)pref.getBTProtocol()) { + case BT::TCP_uTP: + sessionSettings.enable_incoming_tcp = true; + sessionSettings.enable_outgoing_tcp = true; + sessionSettings.enable_incoming_utp = true; + sessionSettings.enable_outgoing_utp = true; + break; + case BT::TCP: + sessionSettings.enable_incoming_tcp = true; + sessionSettings.enable_outgoing_tcp = true; + sessionSettings.enable_incoming_utp = false; + sessionSettings.enable_outgoing_utp = false; + break; + case BT::uTP: + sessionSettings.enable_incoming_tcp = false; + sessionSettings.enable_outgoing_tcp = false; + sessionSettings.enable_incoming_utp = true; + sessionSettings.enable_outgoing_utp = true; + break; + default: + Q_ASSERT(0); + break; + } + // uTP rate limiting + sessionSettings.rate_limit_utp = pref.isuTPRateLimited(); #endif qDebug() << "Settings SessionSettings"; setSessionSettings(sessionSettings);