Bug 142684 - cannot specify which network interface to use
Summary: cannot specify which network interface to use
Status: RESOLVED FIXED
Alias: None
Product: ktorrent
Classification: Applications
Component: general (show other bugs)
Version: unspecified
Platform: Debian testing Linux
: NOR wishlist
Target Milestone: ---
Assignee: Joris Guisson
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-03-08 15:37 UTC by Aggelos Economopoulos
Modified: 2008-07-01 18:44 UTC (History)
0 users

See Also:
Latest Commit:
Version Fixed In:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Aggelos Economopoulos 2007-03-08 15:37:56 UTC
Version:           2.0.3 (using KDE KDE 3.5.5)
Installed from:    Debian testing/unstable Packages
OS:                Linux

On a machine with more than one network interface (either physical or alias), ktorrent can't be instructed which one to use. Having a drop down list of interfaces in the settings would be nice (but a text field is sufficient).
Comment 1 Joris Guisson 2007-03-09 20:20:47 UTC
True, don't know when we can add this, but this sounds reasonable.

Note, we are using KDE code to do http announces, so I'm not quite sure if we can force those on one particular interface.
Comment 2 Joris Guisson 2007-07-17 19:07:18 UTC
SVN commit 689109 by guisson:

Changes :
- Added ChangeLog
- Added first part of advanced pref page
- Added new feature to select which network interface to use

BUG: 142684



 A             ChangeLog  
 M  +1 -1      ktorrent/CMakeLists.txt  
 A             ktorrent/advancedpref.ui  
 M  +2 -1      ktorrent/gui.cpp  
 M  +46 -1     ktorrent/prefdialog.cpp  
 M  +3 -0      ktorrent/view.cpp  
 M  +1 -1      libktorrent/CMakeLists.txt  
 M  +2 -1      libktorrent/dht/rpcserver.cpp  
 M  +33 -0     libktorrent/interfaces/functions.cpp  
 M  +6 -0      libktorrent/interfaces/functions.h  
 M  +6 -1      libktorrent/ktorrent.kcfg  
 M  +5 -3      libktorrent/net/socket.cpp  
 M  +1 -1      libktorrent/net/socket.h  
 M  +3 -2      libktorrent/torrent/server.cpp  


--- branches/ktorrent/kde4port/ktorrent/CMakeLists.txt #689108:689109
@@ -20,7 +20,7 @@
 	scandlg.cpp
 	trayicon.cpp)
 
-kde4_add_ui_files(ktorrent_SRC fileselectdlg.ui globalpref.ui scandlg.ui generalpref.ui)
+kde4_add_ui_files(ktorrent_SRC fileselectdlg.ui globalpref.ui scandlg.ui generalpref.ui advancedpref.ui)
 kde4_add_executable(ktorrent ${ktorrent_SRC})
 
 target_link_libraries(ktorrent ktideal ktcore ${KDE4_KDEUI_LIBS})
--- branches/ktorrent/kde4port/ktorrent/gui.cpp #689108:689109
@@ -86,7 +86,6 @@
 		rc->setIcon(KIcon("tab-remove"));
 		connect(rc,SIGNAL(clicked()),this,SLOT(closeTab()));
 
-		loadState(KGlobal::config());
 		applySettings();
 		connect(core,SIGNAL(settingsChanged()),this,SLOT(applySettings()));
 
@@ -99,6 +98,8 @@
 		}
 		else
 			tray_icon->hide();
+		
+		loadState(KGlobal::config());
 	}
 
 	GUI:: ~GUI()
--- branches/ktorrent/kde4port/ktorrent/prefdialog.cpp #689108:689109
@@ -20,13 +20,19 @@
  ***************************************************************************/
 #include <klocale.h>
 #include <kconfigdialogmanager.h>
+
+#include <solid/device.h>
+#include <solid/networkinterface.h>
+
 #include <interfaces/functions.h>
 #include <interfaces/prefpageinterface.h>
+
 #include "settings.h"
 #include "prefdialog.h"
 #include "core.h"
 #include "ui_globalpref.h"
 #include "ui_generalpref.h"
+#include "ui_advancedpref.h"
 
 namespace kt
 {
@@ -44,7 +50,7 @@
 	class GeneralPref : public PrefPageInterface,public Ui_GeneralPref
 	{
 	public:
-		GeneralPref(QWidget* parent) : PrefPageInterface(Settings::self(),i18n("General"),"settings",parent)
+		GeneralPref(QWidget* parent) : PrefPageInterface(Settings::self(),i18n("General"),"configure",parent)
 		{
 			setupUi(this);
 			kcfg_tempDir->setMode(KFile::Directory|KFile::ExistingOnly|KFile::LocalOnly);
@@ -94,6 +100,44 @@
 		}
 	};
 
+	class AdvancedPref : public PrefPageInterface,public Ui_AdvancedPref
+	{
+	public:
+		AdvancedPref(QWidget* parent) : PrefPageInterface(Settings::self(),i18n("Advanced"),"configure",parent)
+		{
+			setupUi(this);
+		}
+
+		virtual ~AdvancedPref()
+		{
+		}
+
+		void loadSettings()
+		{
+			kcfg_httpTrackerProxy->setEnabled(Settings::doNotUseKDEProxy());
+
+			kcfg_networkInterface->addItem(KIcon("network-wired"),i18n("All interfaces"));
+
+			// get all the network devices and add them to the combo box
+			QList<Solid::Device> netlist = Solid::Device::listFromType(Solid::DeviceInterface::NetworkInterface);
+			foreach (Solid::Device device,netlist)
+			{
+				Solid::NetworkInterface* netdev = device.as<Solid::NetworkInterface>();
+				if (netdev)
+					kcfg_networkInterface->addItem(
+							KIcon(netdev->isWireless() ? "network-wireless" : "network-wired"),
+							netdev->ifaceName());
+			}
+		}
+
+		void loadDefaults()
+		{
+			loadSettings();
+		}
+
+	};
+
+
 	PrefDialog::PrefDialog(QWidget* parent,Core* core) : KConfigDialog(parent,"settings",Settings::self())
 	{
 		KConfigDialogManager::propertyMap()->insert("KUrlRequester","url");
@@ -101,6 +145,7 @@
 		connect(this,SIGNAL(settingsChanged(const QString &)),core,SLOT(applySettings()));
 		addPrefPage(new GlobalPref(this));
 		addPrefPage(new GeneralPref(this));
+		addPrefPage(new AdvancedPref(this));
 	}
 
 	PrefDialog::~PrefDialog()
--- branches/ktorrent/kde4port/ktorrent/view.cpp #689108:689109
@@ -44,6 +44,9 @@
 		setContextMenuPolicy(Qt::CustomContextMenu);
 		setRootIsDecorated(false);
 		setSortingEnabled(true);
+		setAlternatingRowColors(true);
+		setSelectionMode(QAbstractItemView::ExtendedSelection);
+		setSelectionBehavior(QAbstractItemView::SelectRows);
 
 		QStringList columns;
 		columns << i18n("Name") 
--- branches/ktorrent/kde4port/libktorrent/CMakeLists.txt #689108:689109
@@ -164,7 +164,7 @@
 kde4_add_library(ktcore SHARED ${libktorrent_SRC})
 
 # target_link_libraries(ktorrent ${KDE4_KPARTS_LIBS} -lgmp)
-target_link_libraries(ktcore ${KDE4_KDEUI_LIBS} -lkio -lkparts -lgmp)
+target_link_libraries(ktcore ${KDE4_KDEUI_LIBS} -lkio -lkparts -lsolid -lgmp)
 set_target_properties(ktcore PROPERTIES VERSION 1.0.0 SOVERSION 1 )
 install(TARGETS ktcore  DESTINATION ${LIB_INSTALL_DIR} )
 
--- branches/ktorrent/kde4port/libktorrent/dht/rpcserver.cpp #689108:689109
@@ -26,6 +26,7 @@
 #include <bcodec/bnode.h>
 #include <bcodec/bdecoder.h>
 #include <bcodec/bencoder.h>
+#include <interfaces/functions.h>
 #include <k3socketdevice.h>
 #include "rpcserver.h"
 #include "rpccall.h"
@@ -63,7 +64,7 @@
 	void RPCServer::start()
 	{
 		sock->setBlocking(true);
-		if (!sock->bind(QString::null,QString::number(port)))
+		if (!sock->bind(kt::NetworkInterfaceIPAddress(kt::NetworkInterface()),QString::number(port)))
 		{
 			Out(SYS_DHT|LOG_IMPORTANT) << "DHT: Failed to bind to UDP port " << port << " for DHT" << endl;
 		}
--- branches/ktorrent/kde4port/libktorrent/interfaces/functions.cpp #689108:689109
@@ -18,9 +18,12 @@
  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.          *
  ***************************************************************************/
 #include <qdatetime.h>
+#include <QNetworkInterface>
 #include <klocale.h>
 #include <kglobal.h>
 #include <kstandarddirs.h>
+#include <solid/device.h>
+#include <solid/networkinterface.h>
 #include <util/functions.h>
 #include <torrent/downloader.h>
 #include <torrent/choker.h>
@@ -134,4 +137,34 @@
 			Tracker::setCustomIP(QString::null);
 	}
 
+	QString NetworkInterface()
+	{
+		if (Settings::networkInterface() == 0)
+			return QString::null;
+
+		QList<Solid::Device> netlist = Solid::Device::listFromType(Solid::DeviceInterface::NetworkInterface);
+		if (Settings::networkInterface() - 1 > netlist.count())
+			return QString::null;
+		
+
+		Solid::NetworkInterface* netdev = netlist[Settings::networkInterface() - 1].as<Solid::NetworkInterface>();
+		if (!netdev)
+			return QString::null;
+
+		return netdev->ifaceName();
+	}
+	
+	QString NetworkInterfaceIPAddress(const QString & iface)
+	{
+		QNetworkInterface ni = QNetworkInterface::interfaceFromName(iface);
+		if (!ni.isValid())
+			return QString::null;
+
+		QList<QNetworkAddressEntry> addr_list = ni.addressEntries();
+		if (addr_list.count() == 0)
+			return QString::null;
+		else
+			return addr_list.front().ip().toString();
+	}
+
 }
--- branches/ktorrent/kde4port/libktorrent/interfaces/functions.h #689108:689109
@@ -32,6 +32,12 @@
 	KTORRENT_EXPORT QString DurationToString(bt::Uint32 nsecs);
 	KTORRENT_EXPORT QString DataDir();
 	KTORRENT_EXPORT void ApplySettings();
+
+	/// Get the network interface which needs to be used (this will return the name e.g. eth0, wlan0 ...)
+	KTORRENT_EXPORT QString NetworkInterface(); 
+
+	/// Get the IP address of the network interface
+	KTORRENT_EXPORT QString NetworkInterfaceIPAddress(const QString & iface);
 			
 	template<class T> int CompareVal(T a,T b)
 	{
--- branches/ktorrent/kde4port/libktorrent/ktorrent.kcfg #689108:689109
@@ -177,7 +177,7 @@
 			<default code="true">QString::null</default>
 		</entry>
 			<entry name="eta" type="Int">
-			<label>ET algorithm</label>
+			<label>Algorithm to estimate the time when a torrent is finished</label>
 			<default>0</default>
 		</entry>
 		<entry name="diskPrealloc" type="Bool">
@@ -212,5 +212,10 @@
 			<default>0</default>
 			<min>0</min>
 		</entry>
+		<entry name="networkInterface" type="Int">
+			<default>0</default>
+			<min>0</min>
+			<max>255</max>
+		</entry>
 	</group>
 </kcfg>
--- branches/ktorrent/kde4port/libktorrent/net/socket.cpp #689108:689109
@@ -131,22 +131,24 @@
 		return true;
 	}
 	
-	bool Socket::bind(Uint16 port,bool also_listen)
+	bool Socket::bind(const QString & ip,Uint16 port,bool also_listen)
 	{
 		struct sockaddr_in addr;
 		memset(&addr,0,sizeof(struct sockaddr_in));
 		addr.sin_family = AF_INET;
 		addr.sin_port = htons(port);
+		if (!ip.isNull())
+			inet_aton(ip.toAscii(),&addr.sin_addr);
 	
 		if (::bind(m_fd,(struct sockaddr*)&addr,sizeof(struct sockaddr)) < 0)
 		{
-			Out(SYS_CON|LOG_IMPORTANT) << QString("Cannot bind to port %1 : %2").arg(port).arg(strerror(errno)) << endl;
+			Out(SYS_CON|LOG_IMPORTANT) << QString("Cannot bind to port %1:%2 : %3").arg(ip).arg(port).arg(strerror(errno)) << endl;
 			return false;
 		}
 
 		if (also_listen && listen(m_fd,5) < 0)
 		{
-			Out(SYS_CON|LOG_IMPORTANT) << QString("Cannot listen to port %1 : %2").arg(port).arg(strerror(errno)) << endl;
+			Out(SYS_CON|LOG_IMPORTANT) << QString("Cannot listen to port %1:%2 : %3").arg(ip).arg(port).arg(strerror(errno)) << endl;
 			return false;
 		}
 
--- branches/ktorrent/kde4port/libktorrent/net/socket.h #689108:689109
@@ -49,7 +49,7 @@
 		bool connectTo(const Address & addr);
 		/// See if a connectTo was succesfull in non blocking mode
 		bool connectSuccesFull();
-		bool bind(Uint16 port,bool also_listen);
+		bool bind(const QString & ip,Uint16 port,bool also_listen);
 		int send(const bt::Uint8* buf,int len);
 		int recv(bt::Uint8* buf,int max_len);
 		int sendTo(const bt::Uint8* buf,int size,const Address & addr);
--- branches/ktorrent/kde4port/libktorrent/torrent/server.cpp #689108:689109
@@ -27,6 +27,7 @@
 #include <peer/peermanager.h>
 #include <peer/serverauthenticate.h>
 #include <peer/authenticationmonitor.h>
+#include <interfaces/functions.h>
 
 #include "globals.h"
 #include "torrent.h"
@@ -72,8 +73,8 @@
 		delete sn; 
 		sn = 0;
 		sock = new net::Socket(true);
-		
-		if (sock->bind(port,true))
+		QString ip = kt::NetworkInterfaceIPAddress(kt::NetworkInterface());	
+		if (sock->bind(ip,port,true))
 		{
 			sock->setNonBlocking();
 			sn = new QSocketNotifier(sock->fd(),QSocketNotifier::Read,this);
Comment 3 Phill Upson 2008-07-01 17:23:21 UTC
Hi,  I have just configured a virtual adapter from eth0 for torrents, so i can apply a static address to just that but leave dhcp running everything else.  I noticed afterwards that KTorrent only lists the physical adapters ALL, lo, eth0 and eth1 3 times, but not my new virtual interface eth0:one.  It does appear to be seeding whilst set to All Interfaces, but it would be preferable to target just this adapter.  Also for reference, I have confirmed with ifconfig that eth0:one exists and has an ip, it is also reachable externally.

Thanks in advance

Phill Upson
Comment 4 Joris Guisson 2008-07-01 18:44:25 UTC
The multiple listings is a bug which is already fixed.

As for the virtual adaptor, I had no problem with a tunnel adaptor when I was testing IPv6, it got picked up. Maybe you should try restarting ktorrent, and see if it is then found.