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