diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2009-05-02 01:32:29 -0400 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2009-05-02 01:32:29 -0400 |
commit | be2cc8f6d343159df4fe3e1f949ed33a815f87a9 (patch) | |
tree | fbe9912845275f85f2187cd518f390d898ea59be | |
download | QtBonjour-be2cc8f6d343159df4fe3e1f949ed33a815f87a9.tar.xz QtBonjour-be2cc8f6d343159df4fe3e1f949ed33a815f87a9.zip |
-rw-r--r-- | DnsDisplay.cpp | 25 | ||||
-rw-r--r-- | DnsDisplay.h | 14 | ||||
-rw-r--r-- | QtBonjour.pro | 12 | ||||
-rw-r--r-- | main.cpp | 11 | ||||
-rw-r--r-- | mdns.cpp | 210 | ||||
-rw-r--r-- | mdns.h | 145 |
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 + @@ -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 |