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"