00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <netinet/in.h>
00022 #include <QtCore/QEventLoop>
00023 #include <QtGui/QApplication>
00024 #include <kdebug.h>
00025 #include "remoteservice.h"
00026 #include "servicebase_p.h"
00027 #include "mdnsd-responder.h"
00028 #include "mdnsd-sdevent.h"
00029
00030 namespace DNSSD
00031 {
00032 void resolve_callback ( DNSServiceRef,
00033 DNSServiceFlags,
00034 uint32_t,
00035 DNSServiceErrorType errorCode,
00036 const char*,
00037 const char *hosttarget,
00038 uint16_t port,
00039 uint16_t txtLen,
00040 const unsigned char *txtRecord,
00041 void *context
00042 );
00043
00044 #define K_D RemoteServicePrivate* d=static_cast<RemoteServicePrivate*>(this->d)
00045
00046 class RemoteServicePrivate : public Responder, public ServiceBasePrivate
00047 {
00048 public:
00049 RemoteServicePrivate(RemoteService* parent, const QString& name,const QString& type,const QString& domain) :
00050 Responder(), ServiceBasePrivate(name, type, domain, QString(), 0), m_resolved(false), m_parent(parent)
00051 {}
00052 bool m_resolved;
00053 RemoteService* m_parent;
00054 virtual void customEvent(QEvent* event);
00055 };
00056
00057 RemoteService::RemoteService(const QString& name,const QString& type,const QString& domain)
00058 : ServiceBase(new RemoteServicePrivate(this, name, type, domain))
00059 {
00060 }
00061
00062
00063 RemoteService::~RemoteService()
00064 {}
00065
00066 bool RemoteService::resolve()
00067 {
00068 K_D;
00069 resolveAsync();
00070 while (d->isRunning() && !d->m_resolved) d->process();
00071 d->stop();
00072 return d->m_resolved;
00073 }
00074
00075 void RemoteService::resolveAsync()
00076 {
00077 K_D;
00078 if (d->isRunning()) return;
00079 d->m_resolved = false;
00080 kDebug() << this << ":Starting resolve of : " << d->m_serviceName << " " << d->m_type << " " << d->m_domain << "\n";
00081 DNSServiceRef ref;
00082 if (DNSServiceResolve(&ref,0,0,d->m_serviceName.toUtf8(), d->m_type.toAscii().constData(),
00083 domainToDNS(d->m_domain),(DNSServiceResolveReply)resolve_callback,reinterpret_cast<void*>(d))
00084 == kDNSServiceErr_NoError) d->setRef(ref);
00085 if (!d->isRunning()) emit resolved(false);
00086 }
00087
00088 bool RemoteService::isResolved() const
00089 {
00090 K_D;
00091 return d->m_resolved;
00092 }
00093
00094 void RemoteServicePrivate::customEvent(QEvent* event)
00095 {
00096 if (event->type() == QEvent::User+SD_ERROR) {
00097 stop();
00098 m_resolved=false;
00099 emit m_parent->resolved(false);
00100 }
00101 if (event->type() == QEvent::User+SD_RESOLVE) {
00102 ResolveEvent* rev = static_cast<ResolveEvent*>(event);
00103 m_hostName = rev->m_hostname;
00104 m_port = rev->m_port;
00105 m_textData = rev->m_txtdata;
00106 m_resolved = true;
00107 emit m_parent->resolved(true);
00108 }
00109 }
00110
00111 void RemoteService::virtual_hook(int, void*)
00112 {
00113
00114 }
00115
00116
00117 void resolve_callback ( DNSServiceRef,
00118 DNSServiceFlags,
00119 uint32_t,
00120 DNSServiceErrorType errorCode,
00121 const char*,
00122 const char *hosttarget,
00123 uint16_t port,
00124 uint16_t txtLen,
00125 const unsigned char *txtRecord,
00126 void *context
00127 )
00128 {
00129 QObject *obj = reinterpret_cast<QObject*>(context);
00130 if (errorCode != kDNSServiceErr_NoError) {
00131 ErrorEvent err;
00132 QApplication::sendEvent(obj, &err);
00133 return;
00134 }
00135 char key[256];
00136 int index=0;
00137 unsigned char valueLen;
00138 kDebug() << "Resolve callback\n";
00139 QMap<QString,QByteArray> map;
00140 const void *voidValue = 0;
00141 while (TXTRecordGetItemAtIndex(txtLen,txtRecord,index++,256,key,&valueLen,
00142 &voidValue) == kDNSServiceErr_NoError)
00143 {
00144 if (voidValue) map[QString::fromUtf8(key)]=QByteArray((const char*)voidValue,valueLen);
00145 else map[QString::fromUtf8(key)].clear();
00146 }
00147 ResolveEvent rev(DNSToDomain(hosttarget),ntohs(port),map);
00148 QApplication::sendEvent(obj, &rev);
00149 }
00150
00151
00152 }
00153
00154 #include "remoteservice.moc"