summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2009-05-02 01:32:29 -0400
committerJason A. Donenfeld <Jason@zx2c4.com>2009-05-02 01:32:29 -0400
commitbe2cc8f6d343159df4fe3e1f949ed33a815f87a9 (patch)
treefbe9912845275f85f2187cd518f390d898ea59be
downloadQtBonjour-be2cc8f6d343159df4fe3e1f949ed33a815f87a9.tar.xz
QtBonjour-be2cc8f6d343159df4fe3e1f949ed33a815f87a9.zip
Initial import.HEADmaster
-rw-r--r--DnsDisplay.cpp25
-rw-r--r--DnsDisplay.h14
-rw-r--r--QtBonjour.pro12
-rw-r--r--main.cpp11
-rw-r--r--mdns.cpp210
-rw-r--r--mdns.h145
6 files changed, 417 insertions, 0 deletions
diff --git a/DnsDisplay.cpp b/DnsDisplay.cpp
new file mode 100644
index 0000000..cdb5875
--- /dev/null
+++ b/DnsDisplay.cpp
@@ -0,0 +1,25 @@
+//#define HAVE_DNSSD
+#include "DnsDisplay.h"
+#include "mdns.h"
+
+DnsDisplay::DnsDisplay(QWidget *parent)
+ : QTextBrowser(parent)
+{
+ mdns = new MDNSQuery(this);
+ connect(mdns, SIGNAL(serverlistChanged()), this, SLOT(serverListChanged()));
+ mdns->browse_service("_daap._tcp");
+ serverListChanged();
+}
+void DnsDisplay::serverListChanged()
+{
+ QList<MDNSServer *> servers = mdns->serverlist();
+
+ insertHtml("<ul>");
+ for (int i = 0; i < servers.count(); i++) {
+ MDNSServer *serv = servers.at(i);
+ if (!serv->complete())
+ continue;
+ insertHtml("<li>" + serv->name() + "</li>");
+ }
+ insertHtml("</ul><br>***<br>");
+}
diff --git a/DnsDisplay.h b/DnsDisplay.h
new file mode 100644
index 0000000..6569fb0
--- /dev/null
+++ b/DnsDisplay.h
@@ -0,0 +1,14 @@
+#include <QTextBrowser>
+
+class MDNSQuery;
+
+class DnsDisplay : public QTextBrowser
+{
+ Q_OBJECT
+private:
+ MDNSQuery *mdns;
+public:
+ DnsDisplay(QWidget *parent = 0);
+private slots:
+ void serverListChanged();
+};
diff --git a/QtBonjour.pro b/QtBonjour.pro
new file mode 100644
index 0000000..8d5a36f
--- /dev/null
+++ b/QtBonjour.pro
@@ -0,0 +1,12 @@
+######################################################################
+# Automatically generated by qmake (2.01a) Mon Nov 12 02:24:03 2007
+######################################################################
+
+TEMPLATE = app
+TARGET =
+DEPENDPATH += .
+INCLUDEPATH += .
+
+# Input
+HEADERS += DnsDisplay.h mdns.h
+SOURCES += DnsDisplay.cpp main.cpp mdns.cpp
diff --git a/main.cpp b/main.cpp
new file mode 100644
index 0000000..1cbbb4f
--- /dev/null
+++ b/main.cpp
@@ -0,0 +1,11 @@
+#include <QApplication>
+#include "DnsDisplay.h"
+
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+ DnsDisplay d;
+ d.show();
+ return app.exec();
+}
diff --git a/mdns.cpp b/mdns.cpp
new file mode 100644
index 0000000..91c17d5
--- /dev/null
+++ b/mdns.cpp
@@ -0,0 +1,210 @@
+/**
+ * This file is a part of Esperanza, an XMMS2 Client.
+ *
+ * Copyright (C) 2005-2007 XMMS2 Team
+ *
+ * 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.
+ */
+
+
+#include "mdns.h"
+
+#ifdef HAVE_DNSSD
+#include <dns_sd.h>
+
+static void DNSSD_API
+qr_reply (DNSServiceRef sdRef,
+ DNSServiceFlags flags,
+ uint32_t ifIndex,
+ DNSServiceErrorType errorCode,
+ const char *fullname,
+ uint16_t rrtype,
+ uint16_t rrclass,
+ uint16_t rdlen,
+ const void *rdata,
+ uint32_t ttl,
+ void *context)
+{
+ MDNSQuery *mq = static_cast<MDNSQuery*> (context);
+ const unsigned char *rd = (unsigned char *) rdata;
+
+ QString s = QString::fromAscii (fullname);
+ s = s.left (s.indexOf ("."));
+
+ MDNSServer *serv = mq->server (s);
+ if (!serv) {
+ qWarning ("This shouldn't happen!");
+ return;
+ }
+
+ QString ip;
+ ip.sprintf ("%d.%d.%d.%d", rd[0], rd[1], rd[2], rd[3]);
+ serv->set_ip (ip);
+ mq->serv_complete (serv);
+
+ mq->destroy_sock (sdRef);
+}
+
+static void DNSSD_API
+resolve_reply (DNSServiceRef client,
+ DNSServiceFlags flags,
+ uint32_t ifIndex,
+ DNSServiceErrorType errorCode,
+ const char *fullname,
+ const char *hosttarget,
+ uint16_t opaqueport,
+ uint16_t txtLen,
+ const char *txtRecord,
+ void *context)
+{
+ DNSServiceErrorType err;
+ MDNSQuery *mq = static_cast<MDNSQuery*> (context);
+ union { quint16 s; unsigned char b[2]; } portu = { opaqueport };
+ QString s = QString::fromAscii (fullname);
+ s = s.left (s.indexOf ("."));
+
+ MDNSServer *serv = mq->server (s);
+ if (!serv) {
+ qWarning ("This shouldn't happen!");
+ return;
+ }
+
+ serv->set_port (((quint16) portu.b[0]) << 8 | portu.b[1]);
+ serv->set_hostname (QString::fromAscii (hosttarget));
+
+ DNSServiceRef c2;
+ err = DNSServiceQueryRecord (&c2, 0,
+ kDNSServiceInterfaceIndexAny,
+ hosttarget,
+ kDNSServiceType_A,
+ kDNSServiceClass_IN,
+ qr_reply, mq);
+
+ if (err != kDNSServiceErr_NoError) {
+ qWarning ("error from query record!");
+ }
+
+ mq->add_fd (c2);
+
+ mq->destroy_sock (client);
+}
+
+static void DNSSD_API
+browse_reply (DNSServiceRef client,
+ DNSServiceFlags flags,
+ uint32_t ifIndex,
+ DNSServiceErrorType errorCode,
+ const char *replyName,
+ const char *replyType,
+ const char *replyDomain,
+ void *context)
+{
+ DNSServiceErrorType err;
+ MDNSQuery *mq = static_cast<MDNSQuery*> (context);
+ bool remove = (flags & kDNSServiceFlagsAdd) ? false : true;
+
+ if (!remove) {
+ DNSServiceRef c2;
+ MDNSServer *server = new MDNSServer (QString::fromAscii (replyName),
+ QString::fromAscii (replyDomain));
+
+ err = DNSServiceResolve (&c2, 0, kDNSServiceInterfaceIndexAny,
+ replyName, mq->service ().toAscii (), "local",
+ (DNSServiceResolveReply)resolve_reply, mq);
+
+ if (err != kDNSServiceErr_NoError) {
+ delete server;
+ qWarning ("failed to run service resolve!");
+ return;
+ }
+
+ mq->add_server (server);
+ mq->add_fd (c2);
+
+ } else {
+ mq->remove_server (QString::fromAscii (replyName));
+ }
+}
+
+
+void
+MDNSQuery::serv_complete (MDNSServer *serv)
+{
+ if (serv->complete ())
+ return;
+
+ serv->set_complete (true);
+ emit serverlistChanged ();
+}
+
+void
+MDNSQuery::destroy_sock (DNSServiceRef client)
+{
+ QSocketNotifier *sn = m_sockets[client];
+ sn->setEnabled (false);
+ delete sn;
+}
+
+void
+MDNSQuery::add_fd (DNSServiceRef client)
+{
+ QSocketNotifier *sn = new QSocketNotifier (DNSServiceRefSockFD (client),
+ QSocketNotifier::Read, this);
+ connect (sn, SIGNAL (activated (int)), this, SLOT (process (int)));
+ sn->setEnabled (true);
+ m_sockets.insert (client, sn);
+ m_sockets_fd.insert (sn->socket (), client);
+}
+
+void
+MDNSQuery::process (int fd)
+{
+ DNSServiceErrorType err;
+ DNSServiceRef ref = m_sockets_fd[fd];
+
+ err = DNSServiceProcessResult (ref);
+ if (err != kDNSServiceErr_NoError) {
+ qWarning ("error in MDNS process!");
+ }
+}
+
+void
+MDNSQuery::browse_service (const QString &service)
+{
+ DNSServiceErrorType err;
+
+ m_service = service;
+
+ err = DNSServiceBrowse (&m_client, 0, kDNSServiceInterfaceIndexAny,
+ service.toAscii (), 0,
+ browse_reply, static_cast<void *> (this));
+ if (err != kDNSServiceErr_NoError) {
+ qWarning ("can't setup the browser!");
+ return;
+ }
+
+ add_fd (m_client);
+}
+
+#endif /* HAVE DNSSD */
+
+MDNSQuery::MDNSQuery (QObject *parent) : QObject (parent)
+{
+}
+
+#ifndef HAVE_DNSSD
+void
+MDNSQuery::browse_service (const QString &service)
+{
+ /* noop */
+}
+#endif
+
diff --git a/mdns.h b/mdns.h
new file mode 100644
index 0000000..89dfbff
--- /dev/null
+++ b/mdns.h
@@ -0,0 +1,145 @@
+/**
+ * This file is a part of Esperanza, an XMMS2 Client.
+ *
+ * Copyright (C) 2005-2007 XMMS2 Team
+ *
+ * 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.
+ */
+
+
+#ifndef __MDNS_H__
+#define __MDNS_H__
+
+#include <QString>
+#include <QHash>
+#include <QList>
+#include <QSocketNotifier>
+#include <QObject>
+
+#ifdef HAVE_DNSSD
+# include <dns_sd.h>
+#endif
+
+class MDNSServer
+{
+ public:
+ MDNSServer (const QString &name, const QString &domain) {
+ m_name = name;
+ m_domain = domain;
+ m_complete = false;
+ };
+
+ QString name () const {
+ return m_name;
+ };
+
+ void set_port (quint16 p) {
+ m_port = p;
+ };
+
+ void set_hostname (const QString &s) {
+ m_hostname = s;
+ };
+
+ void set_ip (const QString &ip) {
+ m_ip = ip;
+ };
+
+ QString ip () const {
+ return m_ip;
+ };
+
+ quint16 port () const {
+ return m_port;
+ };
+
+ void set_complete (bool b) {
+ m_complete = b;
+ };
+
+ bool complete () const {
+ return m_complete;
+ };
+
+ private:
+ QString m_name;
+ QString m_domain;
+ quint16 m_port;
+ QString m_hostname;
+ QString m_ip;
+ bool m_complete;
+
+};
+
+class MDNSQuery : public QObject
+{
+ Q_OBJECT
+ public:
+ MDNSQuery (QObject *parent);
+ void browse_service (const QString &service);
+
+#ifdef HAVE_DNSSD
+ void add_fd (DNSServiceRef);
+ void destroy_sock (DNSServiceRef);
+#endif
+
+ void add_server (MDNSServer *s) {
+ m_servers[s->name ()] = s;
+ };
+
+ void remove_server (const QString &s) {
+ MDNSServer *serv = server (s);
+ if (serv) {
+ m_servers.remove (s);
+ emit serverlistChanged ();
+ delete serv;
+ }
+ };
+
+ QString service () const {
+ return m_service;
+ };
+
+ MDNSServer *server (const QString &name) const {
+ if (m_servers.contains (name))
+ return m_servers[name];
+ return NULL;
+ };
+
+ void serv_complete (MDNSServer *);
+
+ QList<MDNSServer *> serverlist () const {
+ QList<MDNSServer *> ret;
+ for (int i = 0; i < m_servers.keys ().count (); i++) {
+ ret.append (m_servers[m_servers.keys ().at (i)]);
+ }
+ return ret;
+ };
+
+ private slots:
+#ifdef HAVE_DNSSD
+ void process (int);
+#endif
+
+ signals:
+ void serverlistChanged ();
+
+ private:
+#ifdef HAVE_DNSSD
+ QHash<DNSServiceRef, QSocketNotifier *> m_sockets;
+ QHash<int, DNSServiceRef> m_sockets_fd;
+ DNSServiceRef m_client;
+#endif
+ QHash<QString, MDNSServer *> m_servers;
+ QString m_service;
+};
+
+#endif