summaryrefslogtreecommitdiffstats
path: root/plugins/zeroconf
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/zeroconf')
-rw-r--r--plugins/zeroconf/Makefile.am22
-rw-r--r--plugins/zeroconf/avahiservice.cpp341
-rw-r--r--plugins/zeroconf/avahiservice.h113
-rw-r--r--plugins/zeroconf/ktzeroconfplugin.desktop22
-rw-r--r--plugins/zeroconf/localbrowser.cpp47
-rw-r--r--plugins/zeroconf/localbrowser.h39
-rw-r--r--plugins/zeroconf/zeroconfplugin.cpp135
-rw-r--r--plugins/zeroconf/zeroconfplugin.h71
8 files changed, 790 insertions, 0 deletions
diff --git a/plugins/zeroconf/Makefile.am b/plugins/zeroconf/Makefile.am
new file mode 100644
index 0000000..c6870e6
--- /dev/null
+++ b/plugins/zeroconf/Makefile.am
@@ -0,0 +1,22 @@
+INCLUDES = -I$(top_builddir)/libktorrent -I$(top_builddir)/ktorrent/libktorrent \
+ -I$(srcdir)/../../libktorrent $(all_includes)
+
+METASOURCES = AUTO
+
+if COMPILE_ZEROCONF
+kde_module_LTLIBRARIES = ktzeroconfplugin.la
+endif
+
+ktzeroconfplugin_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) $(AVAHI_LIBS) $(AVAHI_QT3_LIBS)
+ktzeroconfplugin_la_SOURCES = localbrowser.cpp avahiservice.cpp \
+ zeroconfplugin.cpp
+
+ktzeroconfplugin_la_LIBADD = $(LIB_KDECORE) $(LIB_KFILE) $(LIB_KPARTS) $(LIB_KDEUI)\
+ $(LIB_QT) ../../libktorrent/libktorrent.la
+
+noinst_HEADERS = zeroconfplugin.h
+
+kde_services_DATA = ktzeroconfplugin.desktop
+KDE_CXXFLAGS = $(USE_EXCEPTIONS) $(USE_RTTI)
+
+
diff --git a/plugins/zeroconf/avahiservice.cpp b/plugins/zeroconf/avahiservice.cpp
new file mode 100644
index 0000000..a190d8e
--- /dev/null
+++ b/plugins/zeroconf/avahiservice.cpp
@@ -0,0 +1,341 @@
+/***************************************************************************
+ * Copyright (C) 2006 by Lesly Weyts and Kevin Andre *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 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 General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+#include <util/log.h>
+#include <torrent/peerid.h>
+#include <avahi-common/watch.h>
+#include <avahi-qt3/qt-watch.h>
+#include "localbrowser.h"
+#include "avahiservice.h"
+
+using namespace bt;
+
+namespace kt
+{
+
+ void group_callback(AvahiEntryGroup* g, AvahiEntryGroupState state, void* userdata)
+ {
+ AvahiService* service = reinterpret_cast<AvahiService*>(userdata);
+
+ if (g == service->group)
+ {
+ switch (state)
+ {
+ case AVAHI_ENTRY_GROUP_ESTABLISHED:
+ break;
+ case AVAHI_ENTRY_GROUP_COLLISION:
+ Out(SYS_ZCO|LOG_DEBUG) << "ZC: Entry group collision." << endl;
+ break;
+ case AVAHI_ENTRY_GROUP_FAILURE:
+ Out(SYS_ZCO|LOG_DEBUG) << "ZC: Entry group failure." << endl;
+ break;
+ case AVAHI_ENTRY_GROUP_UNCOMMITED:
+ Out(SYS_ZCO|LOG_DEBUG) << "ZC: Entry group uncommited." << endl;
+ break;
+ case AVAHI_ENTRY_GROUP_REGISTERING:
+ ;
+ }
+ }
+ }
+
+ void publish_service(AvahiService* service, AvahiClient *c)
+ {
+ assert(c);
+
+ if (!service->group)
+ {
+ if (!(service->group = avahi_entry_group_new(c, group_callback, service)))
+ {
+ Out(SYS_ZCO|LOG_DEBUG) << "ZC: avahi_entry_group_new failed." << endl;
+ return;
+ }
+ }
+
+ const char* name = avahi_strdup(QString("%1__%2%3").arg(service->id).arg((rand() % 26) + 65).arg((rand() % 26) + 65).ascii());
+ const char* type = avahi_strdup("_bittorrent._tcp");
+ const char* subtype = avahi_strdup(QString("_" + service->infoHash + "._sub._bittorrent._tcp").ascii());
+
+ if (avahi_entry_group_add_service(
+ service->group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
+ (AvahiPublishFlags)0, name, type, NULL, NULL, service->port, NULL))
+ {
+ if (avahi_client_errno(c) != -8)
+ Out(SYS_ZCO|LOG_DEBUG) << QString("ZC: Failed to add the service (%i).").arg(avahi_client_errno(c)) << endl;
+ else
+ publish_service(service, c);
+ return;
+ }
+
+ if (avahi_entry_group_add_service_subtype(
+ service->group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
+ (AvahiPublishFlags)0, name, type, NULL, subtype))
+ {
+ Out(SYS_ZCO|LOG_DEBUG) << QString("ZC: Failed to add the service subtype (%i).").arg( avahi_client_errno(c)) << endl;
+ return;
+ }
+
+ if (avahi_entry_group_commit(service->group))
+ {
+ Out(SYS_ZCO|LOG_DEBUG) << "ZC: Failed to commit the entry group." << endl;
+ return;
+ }
+ }
+
+ void publisher_callback(AvahiClient* c, AvahiClientState state, void* userdata)
+ {
+ if (!c)
+ return;
+
+ AvahiService* service = reinterpret_cast<AvahiService*>(userdata);
+
+ switch (state) {
+ case AVAHI_CLIENT_S_RUNNING:
+ {
+ if (!service->group)
+ publish_service(service, c);
+ break;
+ }
+ case AVAHI_CLIENT_FAILURE:
+ {
+ Out(SYS_ZCO|LOG_DEBUG) << "Failure when publishing." << endl;
+ break;
+ }
+ case AVAHI_CLIENT_S_COLLISION:
+ case AVAHI_CLIENT_S_REGISTERING:
+ {
+ if (service->group)
+ avahi_entry_group_reset(service->group);
+ break;
+ }
+ case AVAHI_CLIENT_CONNECTING:
+ ;
+ }
+ }
+
+ void listener_callback(AvahiClient* c, AvahiClientState state, void* userdata)
+ {
+ assert(c);
+
+ AvahiService* service = reinterpret_cast<AvahiService*>(userdata);
+
+ if (state == AVAHI_CLIENT_FAILURE)
+ {
+ Out(SYS_ZCO|LOG_DEBUG) << "ZC: Server connection failure." << endl;
+ }
+ }
+
+ void resolve_callback(
+ AvahiServiceResolver* r,
+ AVAHI_GCC_UNUSED AvahiIfIndex interface,
+ AVAHI_GCC_UNUSED AvahiProtocol protocol,
+ AvahiResolverEvent event,
+ const char* name,
+ AVAHI_GCC_UNUSED const char* type,
+ AVAHI_GCC_UNUSED const char* domain,
+ AVAHI_GCC_UNUSED const char* host_name,
+ const AvahiAddress* address,
+ uint16_t port,
+ AVAHI_GCC_UNUSED AvahiStringList* txt,
+ AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
+ void* userdata)
+ {
+ assert(r);
+
+ switch (event) {
+ case AVAHI_RESOLVER_FAILURE:
+ {
+ Out(SYS_ZCO|LOG_DEBUG) << "ZC: Resolver failed." << endl;
+ break;
+ }
+ case AVAHI_RESOLVER_FOUND:
+ {
+ AvahiService* service = reinterpret_cast<AvahiService*>(userdata);
+
+ QString realname = QString(name);
+ realname.truncate(realname.length() - 5);
+
+ if (service->id != QString(realname))
+ {
+ char a[AVAHI_ADDRESS_STR_MAX];
+ avahi_address_snprint(a, sizeof(a), address);
+ const char* ip = a;
+ LocalBrowser::insert(bt::PeerID(realname.ascii()));
+
+ Out(SYS_ZCO|LOG_NOTICE) << "ZC: found local peer " << ip << ":" << port << endl;
+ service->addPeer(ip,port,true);
+ service->emitPeersReady();
+ }
+ }
+ }
+ avahi_service_resolver_free(r);
+ }
+
+ void browser_callback(
+ AvahiServiceBrowser* b,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ AvahiBrowserEvent event,
+ const char* name,
+ const char* type,
+ const char* domain,
+ AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
+ void* userdata)
+ {
+ assert(b);
+
+ AvahiService* service = reinterpret_cast<AvahiService*>(userdata);
+
+ switch (event) {
+ case AVAHI_BROWSER_FAILURE:
+ {
+ Out(SYS_ZCO|LOG_DEBUG) << "ZC: Browser failure." << endl;
+ break;
+ }
+ case AVAHI_BROWSER_NEW:
+ {
+ if (!(avahi_service_resolver_new(service->listener, interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, (AvahiLookupFlags)0, resolve_callback, userdata)))
+ Out(SYS_ZCO|LOG_DEBUG) << "ZC: Failed to resolve the service." << endl;
+ break;
+ }
+ case AVAHI_BROWSER_REMOVE:
+ {
+ QString realname = QString(name);
+ realname.truncate(realname.length() - 5);
+
+ LocalBrowser::remove(bt::PeerID(realname.ascii()));
+
+ Out(SYS_ZCO|LOG_DEBUG) << "ZC: Browser removed." << endl;
+ break;
+ }
+ case AVAHI_BROWSER_ALL_FOR_NOW:
+ case AVAHI_BROWSER_CACHE_EXHAUSTED:
+ ;
+ }
+ }
+
+ AvahiService::AvahiService(const bt::PeerID& id,bt::Uint16 port, const bt::SHA1Hash & infoHash)
+ : group(0), publisher_poll(0), listener_poll(0),publisher(0), listener(0), browser(0)
+ {
+ started = false;
+
+ this->id = id.toString();
+ this->port = port;
+ this->infoHash = infoHash.toString();
+ }
+
+ AvahiService::~AvahiService()
+ {
+ stop(0);
+ }
+
+ void AvahiService::stop(bt::WaitJob*)
+ {
+ if (started)
+ {
+ started = false;
+
+ publisher_poll = 0;
+ if (publisher)
+ {
+ avahi_client_free(publisher);
+ publisher = 0;
+ }
+
+ listener_poll = 0;
+ if (listener)
+ {
+ avahi_client_free(listener);
+ listener = 0;
+ }
+ }
+ }
+
+ void AvahiService::start()
+ {
+ started = startPublishing() && startBrowsing();
+ }
+
+ bool AvahiService::startPublishing()
+ {
+ group = NULL;
+ publisher_poll = NULL;
+ publisher = NULL;
+
+ if (!(publisher_poll = avahi_qt_poll_get()))
+ {
+ Out(SYS_ZCO|LOG_DEBUG) << "ZC: Failed to create a poll for publishing." << endl;
+ stop();
+ return false;
+ }
+
+ publisher = avahi_client_new(publisher_poll, AVAHI_CLIENT_NO_FAIL, publisher_callback, this, NULL);
+
+ if (!(publisher))
+ {
+ Out(SYS_ZCO|LOG_DEBUG) << "ZC: Failed to create a client for publishing." << endl;
+ stop();
+ return false;
+ }
+
+ return true;
+ }
+
+ bool AvahiService::startBrowsing()
+ {
+ listener_poll = NULL;
+ listener = NULL;
+ browser = NULL;
+
+ if (!(listener_poll = avahi_qt_poll_get()))
+ {
+ Out(SYS_ZCO|LOG_DEBUG) << "ZC: Failed to create a poll for browsing." << endl;
+ stop();
+ return false;
+ }
+
+ listener = avahi_client_new(listener_poll,AVAHI_CLIENT_NO_FAIL, listener_callback, this, NULL);
+
+ if (!listener)
+ {
+ Out(SYS_ZCO|LOG_DEBUG) << "ZC: Failed to create a client for browsing." << endl;
+ stop();
+ return false;
+ }
+
+ if (!(browser = avahi_service_browser_new(listener, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, avahi_strdup(QString("_" + infoHash + "._sub._bittorrent._tcp").ascii()), NULL, (AvahiLookupFlags)0, browser_callback, this)))
+ {
+ Out(SYS_ZCO|LOG_DEBUG) << "ZC: Failed to create a service browser." << endl;
+ stop();
+ return false;
+ }
+
+ return true;
+ }
+
+ void AvahiService::emitPeersReady()
+ {
+ peersReady(this);
+ }
+
+ void AvahiService::aboutToBeDestroyed()
+ {
+ serviceDestroyed(this);
+ }
+}
+
+#include "avahiservice.moc"
diff --git a/plugins/zeroconf/avahiservice.h b/plugins/zeroconf/avahiservice.h
new file mode 100644
index 0000000..10938d8
--- /dev/null
+++ b/plugins/zeroconf/avahiservice.h
@@ -0,0 +1,113 @@
+/***************************************************************************
+ * Copyright (C) 2006 by Lesly Weyts and Kevin Andre *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 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 General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+#ifndef AVAHI_SERVICE_HH
+#define AVAHI_SERVICE_HH
+
+/**
+ * @author Lesly Weyts and Kevin Andre
+ * @brief Handles everything directly related to Avahi
+ *
+ * This set of functions provide a simple way to use Avahi inside the KTorrent source code.
+ */
+
+#include <cstdlib>
+#include <qstring.h>
+
+
+#include <avahi-client/client.h>
+#include <avahi-client/publish.h>
+#include <avahi-client/lookup.h>
+#include <avahi-common/thread-watch.h>
+#include <avahi-common/malloc.h>
+
+#include <util/sha1hash.h>
+#include <interfaces/peersource.h>
+
+namespace kt
+{
+
+ class AvahiService : public kt::PeerSource
+ {
+ Q_OBJECT
+ public:
+ AvahiService(const bt::PeerID&, bt::Uint16, const bt::SHA1Hash&);
+ virtual ~AvahiService();
+
+ virtual void stop(bt::WaitJob* wjob = 0);
+ virtual void start();
+ virtual void aboutToBeDestroyed();
+
+ void emitPeersReady();
+
+ signals:
+ void serviceDestroyed(AvahiService* av);
+
+ private:
+ bool startPublishing();
+ bool startBrowsing();
+
+ friend void group_callback(AvahiEntryGroup*, AvahiEntryGroupState, void*);
+ friend void publish_service(AvahiService*, AvahiClient*);
+ friend void publisher_callback(AvahiClient*, AvahiClientState, void*);
+ friend void listener_callback(AvahiClient*, AvahiClientState, void*);
+
+ friend void resolve_callback(
+ AvahiServiceResolver*,
+ AvahiIfIndex,
+ AvahiProtocol,
+ AvahiResolverEvent,
+ const char*,
+ const char*,
+ const char*,
+ const char*,
+ const AvahiAddress*,
+ uint16_t,
+ AvahiStringList*,
+ AvahiLookupResultFlags,
+ void*
+ );
+
+ friend void browser_callback(
+ AvahiServiceBrowser*,
+ AvahiIfIndex,
+ AvahiProtocol,
+ AvahiBrowserEvent,
+ const char*,
+ const char*,
+ const char*,
+ AvahiLookupResultFlags,
+ void*
+ );
+
+ QString id;
+ int port;
+ QString infoHash;
+
+ bool started;
+
+ AvahiEntryGroup *group;
+ const AvahiPoll* publisher_poll;
+ const AvahiPoll* listener_poll;
+ AvahiClient* publisher;
+ AvahiClient* listener;
+ AvahiServiceBrowser *browser;
+ };
+}
+
+#endif
diff --git a/plugins/zeroconf/ktzeroconfplugin.desktop b/plugins/zeroconf/ktzeroconfplugin.desktop
new file mode 100644
index 0000000..caf68e1
--- /dev/null
+++ b/plugins/zeroconf/ktzeroconfplugin.desktop
@@ -0,0 +1,22 @@
+[Desktop Entry]
+Name=ZeroConfPlugin
+Name[bg]=Приставка ZeroConf
+Name[de]=ZeroConf-Modul
+Name[es]=Complemento de ZeroConf
+Name[et]=ZeroConfi plugin
+Name[it]=Plugin ZeroConf
+Name[nb]=ZeroConf-modul
+Name[nds]=ZeroConf-Moduul
+Name[pl]=Wtyczka ZeroConf
+Name[pt]='Plugin' do ZeroConf
+Name[pt_BR]=Plugin ZeroConf
+Name[sr]=ZeroConf прикључак
+Name[sr@Latn]=ZeroConf priključak
+Name[sv]=Zeroconf-insticksprogram
+Name[tr]=ZeroConf Eklentisi
+Name[uk]=Втулок ZeroConf
+Name[xx]=xxZeroConfPluginxx
+Name[zh_CN]=ZeroConf 插件
+ServiceTypes=KTorrent/Plugin
+Type=Service
+X-KDE-Library=ktzeroconfplugin
diff --git a/plugins/zeroconf/localbrowser.cpp b/plugins/zeroconf/localbrowser.cpp
new file mode 100644
index 0000000..6306788
--- /dev/null
+++ b/plugins/zeroconf/localbrowser.cpp
@@ -0,0 +1,47 @@
+/***************************************************************************
+ * Copyright (C) 2006 by Lesly Weyts and Kevin Andre *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 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 General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+#include <list>
+#include <torrent/peerid.h>
+#include "localbrowser.h"
+
+
+namespace LocalBrowser
+{
+ static std::list<bt::PeerID> local_peers;
+
+ void remove(bt::PeerID id)
+ {
+ local_peers.remove(id);
+ }
+
+ void insert(bt::PeerID id)
+ {
+ if (!(check(id)))
+ local_peers.push_front(id);
+ }
+
+ bool check(bt::PeerID id)
+ {
+ for (std::list<bt::PeerID>::iterator i = local_peers.begin(); i != local_peers.end(); ++i) {
+ if (*i == id)
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/plugins/zeroconf/localbrowser.h b/plugins/zeroconf/localbrowser.h
new file mode 100644
index 0000000..0e06b99
--- /dev/null
+++ b/plugins/zeroconf/localbrowser.h
@@ -0,0 +1,39 @@
+/***************************************************************************
+ * Copyright (C) 2006 by Lesly Weyts and Kevin Andre *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 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 General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+#ifndef LOCAL_BROWSER_HHHH
+#define LOCAL_BROWSER_HHHH
+
+/**
+ * @author Lesly Weyts and Kevin Andre
+ * @brief Keep track of local peers
+ */
+
+
+
+namespace bt { class PeerID; }
+
+namespace LocalBrowser {
+
+ void remove(bt::PeerID);
+ void insert(bt::PeerID);
+ bool check (bt::PeerID);
+
+
+}
+#endif
diff --git a/plugins/zeroconf/zeroconfplugin.cpp b/plugins/zeroconf/zeroconfplugin.cpp
new file mode 100644
index 0000000..b906843
--- /dev/null
+++ b/plugins/zeroconf/zeroconfplugin.cpp
@@ -0,0 +1,135 @@
+/***************************************************************************
+ * Copyright (C) 2005 by Joris Guisson *
+ * joris.guisson@gmail.com *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 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 General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+#include <kgenericfactory.h>
+#include <util/log.h>
+#include <interfaces/coreinterface.h>
+#include <interfaces/torrentinterface.h>
+#include <torrent/globals.h>
+#include <torrent/server.h>
+#include "zeroconfplugin.h"
+#include "avahiservice.h"
+
+
+#define NAME "Zeroconf"
+#define AUTHOR "Lesly Weyts and Kevin Andre"
+
+K_EXPORT_COMPONENT_FACTORY(ktzeroconfplugin,KGenericFactory<kt::ZeroConfPlugin>("ktzeroconfplugin"))
+
+using namespace bt;
+
+namespace kt
+{
+
+ ZeroConfPlugin::ZeroConfPlugin(QObject* parent, const char* name, const QStringList& args)
+ : Plugin(parent, name,args,NAME,i18n("Zeroconf"),AUTHOR,QString::null,i18n("Finds peers running ktorrent on the local network to share torrents with"),"ktplugins")
+ {
+ services.setAutoDelete(true);
+ }
+
+
+ ZeroConfPlugin::~ZeroConfPlugin()
+ {}
+
+ void ZeroConfPlugin::load()
+ {
+ CoreInterface* core = getCore();
+ connect(core,SIGNAL(torrentAdded( kt::TorrentInterface* )),
+ this,SLOT(torrentAdded( kt::TorrentInterface* )));
+ connect(core,SIGNAL(torrentRemoved( kt::TorrentInterface* )),
+ this,SLOT(torrentRemoved( kt::TorrentInterface* )));
+
+ // go over existing torrents and add them
+ bt::QueueManager* qman = core->getQueueManager();
+ for (QPtrList<kt::TorrentInterface>::iterator i = qman->begin();i != qman->end();i++)
+ {
+ torrentAdded(*i);
+ }
+ }
+
+ void ZeroConfPlugin::unload()
+ {
+ CoreInterface* core = getCore();
+ disconnect(core,SIGNAL(torrentAdded( kt::TorrentInterface* )),
+ this,SLOT(torrentAdded( kt::TorrentInterface* )));
+ disconnect(core,SIGNAL(torrentRemoved( kt::TorrentInterface* )),
+ this,SLOT(torrentRemoved( kt::TorrentInterface*)));
+
+ bt::PtrMap<kt::TorrentInterface*,AvahiService>::iterator i = services.begin();
+ while (i != services.end())
+ {
+ AvahiService* av = i->second;
+ kt::TorrentInterface* ti = i->first;
+ ti->removePeerSource(av);
+ i++;
+ }
+ services.clear();
+ }
+
+ void ZeroConfPlugin::torrentAdded(kt::TorrentInterface* tc)
+ {
+ if (services.contains(tc))
+ return;
+
+ bt::Uint16 port = bt::Globals::instance().getServer().getPortInUse();
+ AvahiService* av = new AvahiService(tc->getOwnPeerID(),port,tc->getInfoHash());
+ services.insert(tc,av);
+ tc->addPeerSource(av);
+ Out(SYS_ZCO|LOG_NOTICE) << "ZeroConf service added for "
+ << tc->getStats().torrent_name << endl;
+ connect(av,SIGNAL(serviceDestroyed( AvahiService* )),
+ this,SLOT(avahiServiceDestroyed( AvahiService* )));
+ }
+
+
+ void ZeroConfPlugin::torrentRemoved(kt::TorrentInterface* tc)
+ {
+ AvahiService* av = services.find(tc);
+ if (!av)
+ return;
+ Out(SYS_ZCO|LOG_NOTICE) << "ZeroConf service removed for "
+ << tc->getStats().torrent_name << endl;
+ tc->removePeerSource(av);
+ services.erase(tc);
+ }
+
+ void ZeroConfPlugin::avahiServiceDestroyed(AvahiService* av)
+ {
+ services.setAutoDelete(false);
+
+ Out(SYS_ZCO|LOG_NOTICE) << "ZeroConf service destroyed " << endl;
+ bt::PtrMap<kt::TorrentInterface*,AvahiService>::iterator i = services.begin();
+ while (i != services.end())
+ {
+ if (i->second == av)
+ {
+ services.erase(i->first);
+ break;
+ }
+ i++;
+ }
+ services.setAutoDelete(true);
+ }
+
+ bool ZeroConfPlugin::versionCheck(const QString & version) const
+ {
+ return version == KT_VERSION_MACRO;
+ }
+}
+#include "zeroconfplugin.moc"
diff --git a/plugins/zeroconf/zeroconfplugin.h b/plugins/zeroconf/zeroconfplugin.h
new file mode 100644
index 0000000..b34e851
--- /dev/null
+++ b/plugins/zeroconf/zeroconfplugin.h
@@ -0,0 +1,71 @@
+/***************************************************************************
+ * Copyright (C) 2005 by Joris Guisson *
+ * joris.guisson@gmail.com *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 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 General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+#ifndef KTZEROCONFPLUGIN_H
+#define KTZEROCONFPLUGIN_H
+
+#include <util/ptrmap.h>
+#include <interfaces/plugin.h>
+
+namespace kt
+{
+ class TorrentInterface;
+ class AvahiService;
+
+ /**
+ * @author Joris Guisson <joris.guisson@gmail.com>
+ *
+ * Plugin which handles the zeroconf service.
+ */
+ class ZeroConfPlugin : public Plugin
+ {
+ Q_OBJECT
+ public:
+ ZeroConfPlugin(QObject* parent, const char* name, const QStringList& args);
+ virtual ~ZeroConfPlugin();
+
+ virtual void load();
+ virtual void unload();
+ virtual bool versionCheck(const QString& version) const;
+
+ private slots:
+ /**
+ * A TorrentInterface was added
+ * @param tc
+ */
+ void torrentAdded(kt::TorrentInterface* tc);
+
+ /**
+ * A TorrentInterface was removed
+ * @param tc
+ */
+ void torrentRemoved(kt::TorrentInterface* tc);
+
+ /**
+ * An AvahiService has been destroyed by the psman
+ */
+ void avahiServiceDestroyed(AvahiService* av);
+
+ private:
+ bt::PtrMap<kt::TorrentInterface*,AvahiService> services;
+ };
+
+}
+
+#endif