From e9fa39a9b4d11654dfbc2271c75f3a883c2b4ac8 Mon Sep 17 00:00:00 2001 From: Harald Sitter Date: Fri, 12 Oct 2018 16:39:18 +0200 Subject: [PATCH] fallback to dnssd service discovery if smb listing failed --- smb/CMakeLists.txt | 14 +++++++-- smb/kio_smb_browse.cpp | 65 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 74 insertions(+), 5 deletions(-) diff --git a/smb/CMakeLists.txt b/smb/CMakeLists.txt index e5526720..f61b6356 100644 --- a/smb/CMakeLists.txt +++ b/smb/CMakeLists.txt @@ -23,14 +23,24 @@ include_directories(${SAMBA_INCLUDE_DIR}) add_library(kio_smb MODULE ${kio_smb_PART_SRCS}) -target_link_libraries(kio_smb KF5::KIOCore KF5::I18n ${SAMBA_LIBRARIES} Qt5::Network) +target_link_libraries(kio_smb + KF5::KIOCore + KF5::I18n + ${SAMBA_LIBRARIES} + Qt5::Network + KF5::DNSSD) else() set(kio_smb_PART_SRCS kio_smb_win.cpp) add_library(kio_smb MODULE ${kio_smb_PART_SRCS}) -target_link_libraries(kio_smb KF5::KIOCore KF5::I18n mpr Qt5::Network) +target_link_libraries(kio_smb + KF5::KIOCore + KF5::I18n + mpr + Qt5::Network + KF5::DNSSD) endif() set_target_properties(kio_smb PROPERTIES OUTPUT_NAME "smb") diff --git a/smb/kio_smb_browse.cpp b/smb/kio_smb_browse.cpp index 1fa0e6fb..a0dbbe2c 100644 --- a/smb/kio_smb_browse.cpp +++ b/smb/kio_smb_browse.cpp @@ -13,6 +13,7 @@ //--------------------------------------------------------------------------- // // Copyright (c) 2000 Caldera Systems, Inc. +// Copyright (c) 2018 Harald Sitter // // 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 @@ -30,14 +31,19 @@ // ///////////////////////////////////////////////////////////////////////////// -#include -#include - #include "kio_smb.h" #include "kio_smb_internal.h" + +#include +#include #include #include +#include + +#include +#include + using namespace KIO; int SMBSlave::cache_stat(const SMBUrl &url, struct stat* st ) @@ -328,12 +334,15 @@ void SMBSlave::listDir( const QUrl& kurl ) qCDebug(KIO_SMB) << "open " << m_current_url.toSmbcUrl() << " " << m_current_url.getType() << " " << dirfd; if(dirfd >= 0) { + uint direntCount = 0; do { qCDebug(KIO_SMB) << "smbc_readdir "; dirp = smbc_readdir(dirfd); if(dirp == 0) break; + ++direntCount; + // Set name QString udsName; const QString dirpName = QString::fromUtf8( dirp->name ); @@ -445,6 +454,56 @@ void SMBSlave::listDir( const QUrl& kurl ) udsentry.clear(); } while (dirp); // checked already in the head + // FIXME: possibly should construct urls or structs? or qhash it? + // one hostName may have multiple services on different ports! + // should we create multiple UDS entries? + // FIXME: no way to determine workgroups? + QStringList hosts; + auto normalizedUrl = url.adjusted(QUrl::NormalizePathSegments); + if (direntCount <= 0 && normalizedUrl.path().isEmpty()) { + // Slaves have no event loop, start one for the poll. + // KDNSSD has an internal timeout which will trigger. + // Bit shitty. Possibly should use the mollet thing of the network: slave + QEventLoop e; + KDNSSD::ServiceBrowser* browser = new KDNSSD::ServiceBrowser("_smb._tcp"); + connect(browser, &KDNSSD::ServiceBrowser::serviceAdded, + this, [&hosts](KDNSSD::RemoteService::Ptr service){ + qDebug() << "ADDED" << service->serviceName() << service->type() << service->domain() << service->hostName() << service->port(); + auto addr = service->serviceName() + "." + service->domain(); + if (hosts.contains(addr)) { + return; + } + hosts.append(addr); + }); + connect(browser, &KDNSSD::ServiceBrowser::serviceRemoved, + this, [&hosts](KDNSSD::RemoteService::Ptr service){ + qDebug() << "REMOVED" << service->serviceName() << service->type() << service->domain() << service->hostName() << service->port(); + hosts.removeAll(service->serviceName() + "." + service->domain()); + }); + connect(browser, &KDNSSD::ServiceBrowser::finished, + &e, &QEventLoop::quit); + browser->startBrowse(); + e.exec(); + + for (auto host : hosts) { + // FIXME: Should be servicename rather than host address maybe? + udsentry.insert( KIO::UDSEntry::UDS_NAME, host); + + udsentry.insert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); + udsentry.insert(KIO::UDSEntry::UDS_ACCESS, (S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)); + + QUrl u("smb://"); + u.setHost(host); + + qCDebug(KIO_SMB) << "list item " << u << "--" << host; + udsentry.insert(KIO::UDSEntry::UDS_URL, u.url()); + udsentry.insert(KIO::UDSEntry::UDS_MIME_TYPE, QString::fromLatin1("application/x-smb-server")); + + listEntry(udsentry); + udsentry.clear(); + } + } + if (dir_is_root) { udsentry.insert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); udsentry.insert(KIO::UDSEntry::UDS_NAME, "."); -- 2.17.1