KDECore
ksrvresolverworker.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <config.h>
00021
00022 #include "ksrvresolverworker_p.h"
00023
00024 #include <sys/types.h>
00025 #include <sys/socket.h>
00026 #include <stdlib.h>
00027
00028 #include <qapplication.h>
00029 #include <qevent.h>
00030
00031 using namespace KNetwork;
00032 using namespace KNetwork::Internal;
00033
00034 namespace
00035 {
00036 struct KSrvStartEvent: public QCustomEvent
00037 {
00038 inline KSrvStartEvent() : QCustomEvent(QEvent::User) { }
00039 };
00040 }
00041
00042 static void sortPriorityClass(KSrvResolverWorker::PriorityClass&)
00043 {
00044
00045 }
00046
00047 bool KSrvResolverWorker::preprocess()
00048 {
00049
00050 if ((flags() & (KResolver::NoSrv | KResolver::UseSrv)) != KResolver::UseSrv)
00051 return false;
00052
00053 QString node = nodeName();
00054 if (node.find('%') != -1)
00055 node.truncate(node.find('%'));
00056
00057 if (node.isEmpty() || node == QString::fromLatin1("*") ||
00058 node == QString::fromLatin1("localhost"))
00059 return false;
00060
00061 encodedName = KResolver::domainToAscii(node);
00062 if (encodedName.isNull())
00063 return false;
00064
00065
00066 if ((familyMask() & KResolver::InternetFamily) == 0)
00067 return false;
00068
00069
00070 bool ok;
00071 serviceName().toUInt(&ok);
00072 if (ok)
00073 return false;
00074
00075
00076 QCString protoname;
00077 int sockettype = socketType();
00078 if (!protocolName().isEmpty())
00079 protoname = protocolName();
00080 else if (protocol() != 0)
00081 {
00082 QStrList names = KResolver::protocolName(protocol());
00083 names.setAutoDelete(true);
00084 if (names.isEmpty())
00085 return false;
00086
00087 protoname = "_";
00088 protoname += names.at(0);
00089 }
00090 else if (sockettype == SOCK_STREAM || sockettype == 0)
00091 protoname = "_tcp";
00092 else if (sockettype == SOCK_DGRAM)
00093 protoname = "_udp";
00094 else
00095 return false;
00096
00097 encodedName.prepend(".");
00098 encodedName.prepend(protoname);
00099 encodedName.prepend(".");
00100 encodedName.prepend(serviceName().latin1());
00101 encodedName.prepend("_");
00102
00103
00104 return true;
00105 }
00106
00107 bool KSrvResolverWorker::run()
00108 {
00109 sem = new QSemaphore(1);
00110
00111 sem->tryAccess(sem->available());
00112
00113 QApplication::postEvent(this, new KSrvStartEvent);
00114
00115
00116 (*sem)++;
00117 delete sem;
00118 sem = 0L;
00119
00120 if (rawResults.isEmpty())
00121 {
00122
00123 KResolver *r = new KResolver(nodeName(), serviceName());
00124 r->setFlags(flags() | KResolver::NoSrv);
00125 r->setFamily(familyMask());
00126 r->setSocketType(socketType());
00127 r->setProtocol(protocol(), protocolName());
00128
00129 enqueue(r);
00130
00131 Entry e;
00132 PriorityClass cl;
00133 e.resolver = r;
00134 cl.entries.append(e);
00135 myResults[0] = cl;
00136
00137 return true;
00138 }
00139 else if (rawResults.count() == 1 && rawResults.first().name == ".")
00140 {
00141
00142 setError(KResolver::NoName);
00143 finished();
00144 return true;
00145 }
00146 else
00147 {
00148
00149 QValueList<QDns::Server>::ConstIterator it = rawResults.begin();
00150 while (it != rawResults.end())
00151 {
00152 const QDns::Server& srv = *it;
00153 PriorityClass& r = myResults[srv.priority];
00154 r.totalWeight += srv.weight;
00155
00156 Entry e;
00157 e.name = srv.name;
00158 e.port = srv.port;
00159 e.weight = srv.weight;
00160 e.resolver = 0L;
00161 r.entries.append(e);
00162
00163 ++it;
00164 }
00165 rawResults.clear();
00166
00167 Results::Iterator mapit;
00168 for (mapit = myResults.begin(); mapit != myResults.end(); ++mapit)
00169 {
00170
00171 sortPriorityClass(*mapit);
00172
00173 QValueList<Entry>& entries = (*mapit).entries;
00174
00175
00176 for (QValueList<Entry>::Iterator it = entries.begin();
00177 it != entries.end(); ++it)
00178 {
00179 Entry &e = *it;
00180
00181 KResolver* r = new KResolver(e.name, QString::number(e.port));
00182 r->setFlags(flags() | KResolver::NoSrv);
00183 r->setFamily(familyMask());
00184 r->setSocketType(socketType());
00185 r->setProtocol(protocol(), protocolName());
00186
00187 enqueue(r);
00188 e.resolver = r;
00189 }
00190 }
00191
00192 return true;
00193 }
00194 }
00195
00196 bool KSrvResolverWorker::postprocess()
00197 {
00198 setError(KResolver::NoName);
00199 if (myResults.isEmpty())
00200 return false;
00201
00202 Results::Iterator mapit, mapend;
00203 for (mapit = myResults.begin(), mapend = myResults.end();
00204 mapit != mapend; ++mapit)
00205 {
00206 QValueList<Entry>::Iterator it = (*mapit).entries.begin(),
00207 end = (*mapit).entries.end();
00208 for ( ; it != end; ++it)
00209 {
00210 Entry &e = *it;
00211 KResolverResults r = e.resolver->results();
00212 if (r.isEmpty() && results.isEmpty())
00213 setError(r.error(), r.systemError());
00214 else
00215 {
00216 setError(KResolver::NoError);
00217 results += r;
00218 }
00219 }
00220 }
00221
00222 finished();
00223 return true;
00224 }
00225
00226 void KSrvResolverWorker::customEvent(QCustomEvent*)
00227 {
00228 dns = new QDns(QString::fromLatin1(encodedName), QDns::Srv);
00229 QObject::connect(dns, SIGNAL(resultsReady()), this, SLOT(dnsResultsReady()));
00230 }
00231
00232 void KSrvResolverWorker::dnsResultsReady()
00233 {
00234 (*sem)--;
00235 rawResults = dns->servers();
00236 dns->deleteLater();
00237 dns = 0L;
00238 }
00239
00240 namespace KNetwork
00241 {
00242 namespace Internal
00243 {
00244
00245 void initSrvWorker() KDE_NO_EXPORT;
00246 void initSrvWorker()
00247 {
00248 if (getenv("KDE_NO_SRV") != NULL)
00249 return;
00250
00251 KResolverWorkerFactoryBase::registerNewWorker(new KResolverWorkerFactory<KSrvResolverWorker>);
00252 }
00253
00254 }
00255 }
00256
00257 #include "ksrvresolverworker_p.moc"