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