File indexing completed on 2024-04-28 15:22:06

0001 /*
0002     This file is part of the KDE project
0003 
0004     SPDX-FileCopyrightText: 2004 Jakub Stachowski <qbast@go2.pl>
0005 
0006     SPDX-License-Identifier: LGPL-2.0-or-later
0007 */
0008 
0009 #include "domainbrowser.h"
0010 #include "mdnsd-domainbrowser_p.h"
0011 #include "mdnsd-responder.h"
0012 #include "mdnsd-sdevent.h"
0013 #include "remoteservice.h"
0014 
0015 #include <QCoreApplication>
0016 #include <QHash>
0017 #include <QStringList>
0018 
0019 namespace KDNSSD
0020 {
0021 void domain_callback(DNSServiceRef, DNSServiceFlags flags, uint32_t, DNSServiceErrorType errorCode, const char *replyDomain, void *context);
0022 
0023 DomainBrowser::DomainBrowser(DomainType type, QObject *parent)
0024     : QObject(parent)
0025     , d(new DomainBrowserPrivate(type, this))
0026 {
0027 }
0028 
0029 DomainBrowser::~DomainBrowser() = default;
0030 
0031 void DomainBrowser::startBrowse()
0032 {
0033     Q_D(DomainBrowser);
0034     if (d->isRunning()) {
0035         return;
0036     }
0037     DNSServiceRef ref;
0038     if (DNSServiceEnumerateDomains(&ref,
0039                                    (d->m_type == Browsing) ? kDNSServiceFlagsBrowseDomains : kDNSServiceFlagsBrowseDomains,
0040                                    0,
0041                                    domain_callback,
0042                                    reinterpret_cast<void *>(d))
0043         == kDNSServiceErr_NoError) {
0044         d->setRef(ref);
0045     }
0046 }
0047 
0048 void DomainBrowserPrivate::customEvent(QEvent *event)
0049 {
0050     if (event->type() == QEvent::User + SD_ERROR) {
0051         stop();
0052     }
0053     if (event->type() == QEvent::User + SD_ADDREMOVE) {
0054         AddRemoveEvent *aev = static_cast<AddRemoveEvent *>(event);
0055         if (aev->m_op == AddRemoveEvent::Add) {
0056             // FIXME: check if domain name is not name+domain (there was some mdnsd weirdness)
0057             if (m_domains.contains(aev->m_domain)) {
0058                 return;
0059             }
0060             m_domains.append(aev->m_domain);
0061             Q_EMIT m_parent->domainAdded(aev->m_domain);
0062         } else {
0063             m_domains.removeAll(aev->m_domain);
0064             Q_EMIT m_parent->domainRemoved(aev->m_domain);
0065         }
0066     }
0067 }
0068 
0069 QStringList DomainBrowser::domains() const
0070 {
0071     Q_D(const DomainBrowser);
0072     return d->m_domains;
0073 }
0074 
0075 bool DomainBrowser::isRunning() const
0076 {
0077     Q_D(const DomainBrowser);
0078     return d->isRunning();
0079 }
0080 
0081 void domain_callback(DNSServiceRef, DNSServiceFlags flags, uint32_t, DNSServiceErrorType errorCode, const char *replyDomain, void *context)
0082 {
0083     QObject *obj = reinterpret_cast<QObject *>(context);
0084     if (errorCode != kDNSServiceErr_NoError) {
0085         ErrorEvent err;
0086         QCoreApplication::sendEvent(obj, &err);
0087     } else {
0088         // domain browser is supposed to return only _additional_ domains
0089         if (flags & kDNSServiceFlagsDefault) {
0090             return;
0091         }
0092         AddRemoveEvent arev((flags & kDNSServiceFlagsAdd) ? AddRemoveEvent::Add : AddRemoveEvent::Remove,
0093                             QString(),
0094                             QString(),
0095                             DNSToDomain(replyDomain),
0096                             !(flags & kDNSServiceFlagsMoreComing));
0097         QCoreApplication::sendEvent(obj, &arev);
0098     }
0099 }
0100 
0101 }
0102 
0103 #include "moc_domainbrowser.cpp"
0104 #include "moc_mdnsd-domainbrowser_p.cpp"