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, 2005 Jakub Stachowski <qbast@go2.pl> 0005 0006 SPDX-License-Identifier: LGPL-2.0-or-later 0007 */ 0008 0009 #include "mdnsd-responder.h" 0010 #include "mdnsd-sdevent.h" 0011 #include "remoteservice.h" 0012 #include "servicebase_p.h" 0013 #include <QCoreApplication> 0014 #include <QDebug> 0015 #include <QEventLoop> 0016 #include <netinet/in.h> 0017 0018 namespace KDNSSD 0019 { 0020 void resolve_callback(DNSServiceRef, 0021 DNSServiceFlags, 0022 uint32_t, 0023 DNSServiceErrorType errorCode, 0024 const char *, 0025 const char *hosttarget, 0026 uint16_t port, 0027 uint16_t txtLen, 0028 const unsigned char *txtRecord, 0029 void *context); 0030 0031 #define KDNSSD_D RemoteServicePrivate *d = static_cast<RemoteServicePrivate *>(this->d.operator->()) 0032 0033 class RemoteServicePrivate : public Responder, public ServiceBasePrivate 0034 { 0035 public: 0036 RemoteServicePrivate(RemoteService *parent, const QString &name, const QString &type, const QString &domain) 0037 : Responder() 0038 , ServiceBasePrivate(name, type, domain, QString(), 0) 0039 , m_resolved(false) 0040 , m_parent(parent) 0041 { 0042 } 0043 bool m_resolved; 0044 RemoteService *m_parent; 0045 virtual void customEvent(QEvent *event); 0046 }; 0047 0048 RemoteService::RemoteService(const QString &name, const QString &type, const QString &domain) 0049 : ServiceBase(new RemoteServicePrivate(this, name, type, domain)) 0050 { 0051 } 0052 0053 RemoteService::~RemoteService() 0054 { 0055 } 0056 0057 bool RemoteService::resolve() 0058 { 0059 KDNSSD_D; 0060 resolveAsync(); 0061 while (d->isRunning() && !d->m_resolved) { 0062 d->process(); 0063 } 0064 d->stop(); 0065 return d->m_resolved; 0066 } 0067 0068 void RemoteService::resolveAsync() 0069 { 0070 KDNSSD_D; 0071 if (d->isRunning()) { 0072 return; 0073 } 0074 d->m_resolved = false; 0075 // qDebug() << this << ":Starting resolve of : " << d->m_serviceName << " " << d->m_type << " " << d->m_domain << "\n"; 0076 DNSServiceRef ref; 0077 if (DNSServiceResolve(&ref, 0078 0, 0079 0, 0080 d->m_serviceName.toUtf8().constData(), 0081 d->m_type.toLatin1().constData(), 0082 domainToDNS(d->m_domain).constData(), 0083 (DNSServiceResolveReply)resolve_callback, 0084 reinterpret_cast<void *>(d)) 0085 == kDNSServiceErr_NoError) { 0086 d->setRef(ref); 0087 } 0088 if (!d->isRunning()) { 0089 Q_EMIT resolved(false); 0090 } 0091 } 0092 0093 bool RemoteService::isResolved() const 0094 { 0095 KDNSSD_D; 0096 return d->m_resolved; 0097 } 0098 0099 void RemoteServicePrivate::customEvent(QEvent *event) 0100 { 0101 if (event->type() == QEvent::User + SD_ERROR) { 0102 stop(); 0103 m_resolved = false; 0104 Q_EMIT m_parent->resolved(false); 0105 } 0106 if (event->type() == QEvent::User + SD_RESOLVE) { 0107 ResolveEvent *rev = static_cast<ResolveEvent *>(event); 0108 m_hostName = rev->m_hostname; 0109 m_port = rev->m_port; 0110 m_textData = rev->m_txtdata; 0111 m_resolved = true; 0112 Q_EMIT m_parent->resolved(true); 0113 } 0114 } 0115 0116 void RemoteService::virtual_hook(int, void *) 0117 { 0118 // BASE::virtual_hook(int, void*); 0119 } 0120 0121 void resolve_callback(DNSServiceRef, 0122 DNSServiceFlags, 0123 uint32_t, 0124 DNSServiceErrorType errorCode, 0125 const char *, 0126 const char *hosttarget, 0127 uint16_t port, 0128 uint16_t txtLen, 0129 const unsigned char *txtRecord, 0130 void *context) 0131 { 0132 QObject *obj = reinterpret_cast<QObject *>(context); 0133 if (errorCode != kDNSServiceErr_NoError) { 0134 ErrorEvent err; 0135 QCoreApplication::sendEvent(obj, &err); 0136 return; 0137 } 0138 char key[256]; 0139 int index = 0; 0140 unsigned char valueLen; 0141 // qDebug() << "Resolve callback\n"; 0142 QMap<QString, QByteArray> map; 0143 const void *voidValue = 0; 0144 while (TXTRecordGetItemAtIndex(txtLen, txtRecord, index++, 256, key, &valueLen, &voidValue) == kDNSServiceErr_NoError) { 0145 if (voidValue) { 0146 map[QString::fromUtf8(key)] = QByteArray((const char *)voidValue, valueLen); 0147 } else { 0148 map[QString::fromUtf8(key)].clear(); 0149 } 0150 } 0151 ResolveEvent rev(DNSToDomain(hosttarget), ntohs(port), map); 0152 QCoreApplication::sendEvent(obj, &rev); 0153 } 0154 0155 } 0156 0157 #include "moc_remoteservice.cpp"