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