File indexing completed on 2024-04-28 04:58:00

0001 /*
0002     SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0003     SPDX-FileCopyrightText: 2019 Harald Sitter <sitter@kde.org>
0004 */
0005 
0006 #include "dnssddiscoverer.h"
0007 #include "kio_smb.h"
0008 
0009 DNSSDDiscovery::DNSSDDiscovery(KDNSSD::RemoteService::Ptr service)
0010     : m_service(service)
0011 {
0012 }
0013 
0014 QString DNSSDDiscovery::udsName() const
0015 {
0016     return m_service->serviceName();
0017 }
0018 
0019 KIO::UDSEntry DNSSDDiscovery::toEntry() const
0020 {
0021     KIO::UDSEntry entry;
0022     entry.reserve(6);
0023     entry.fastInsert(KIO::UDSEntry::UDS_NAME, udsName());
0024 
0025     entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR);
0026     entry.fastInsert(KIO::UDSEntry::UDS_ACCESS, (S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH));
0027     entry.fastInsert(KIO::UDSEntry::UDS_ICON_NAME, "network-server");
0028 
0029     // TODO: it may be better to resolve the host to an ip address. dnssd
0030     //   being able to find a service doesn't mean name resolution is
0031     //   properly set up for its domain. So, we may not be able to resolve
0032     //   this without help from avahi. OTOH KDNSSD doesn't have API for this
0033     //   and from a platform POV we should probably assume that if avahi
0034     //   is functional it is also set up as resolution provider.
0035     //   Given the plugin design on glibc's libnss however I am not sure
0036     //   that assumption will be true all the time. ~sitter, 2018
0037     QUrl u;
0038     u.setScheme(QStringLiteral("smb"));
0039     u.setHost(m_service->hostName());
0040     const int defaultPort = 445;
0041     if (m_service->port() > 0 && m_service->port() != defaultPort) {
0042         u.setPort(m_service->port());
0043     }
0044     u.setPath("/"); // https://bugs.kde.org/show_bug.cgi?id=388922
0045 
0046     entry.fastInsert(KIO::UDSEntry::UDS_URL, u.url());
0047     entry.fastInsert(KIO::UDSEntry::UDS_MIME_TYPE, QStringLiteral("application/x-smb-server"));
0048     return entry;
0049 }
0050 
0051 DNSSDDiscoverer::DNSSDDiscoverer()
0052 {
0053     connect(&m_browser, &KDNSSD::ServiceBrowser::serviceAdded, this, [this](KDNSSD::RemoteService::Ptr service) {
0054         qCDebug(KIO_SMB_LOG) << "DNSSD added:" << service->serviceName() << service->type() << service->domain() << service->hostName() << service->port();
0055         // Manual contains check. We need to use the == of the underlying
0056         // objects, not the pointers. The same service may have >1
0057         // RemoteService* instances representing it, so the == impl of
0058         // RemoteService::Ptr is useless here.
0059         for (const auto &servicePtr : qAsConst(m_services)) {
0060             if (*service == *servicePtr) {
0061                 return;
0062             }
0063         }
0064 
0065         connect(service.data(), &KDNSSD::RemoteService::resolved, this, [this, service] {
0066             ++m_resolvedCount;
0067             Q_EMIT newDiscovery(Discovery::Ptr(new DNSSDDiscovery(service)));
0068             maybeFinish();
0069         });
0070 
0071         // Schedule resolution of hostname. We'll later call resolve
0072         // which will block until the resolution is done. This basically
0073         // gives us a head start on discovery.
0074         service->resolveAsync();
0075         m_services.append(service);
0076     });
0077     connect(&m_browser, &KDNSSD::ServiceBrowser::finished, this, &DNSSDDiscoverer::stop);
0078 }
0079 
0080 void DNSSDDiscoverer::start()
0081 {
0082     m_browser.startBrowse();
0083 }
0084 
0085 void DNSSDDiscoverer::stop()
0086 {
0087     m_browser.disconnect();
0088     m_disconnected = true;
0089     maybeFinish();
0090 }
0091 
0092 bool DNSSDDiscoverer::isFinished() const
0093 {
0094     return m_disconnected && m_services.count() == m_resolvedCount;
0095 }
0096 
0097 void DNSSDDiscoverer::maybeFinish()
0098 {
0099     if (isFinished()) {
0100         Q_EMIT finished();
0101     }
0102 }
0103 
0104 #include "moc_dnssddiscoverer.cpp"