KDECore
k3serversocket.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
00021
00022
00023
00024
00025 #include "k3serversocket.h"
00026
00027 #include <config.h>
00028 #include <config-network.h>
00029
00030 #include <QSocketNotifier>
00031 #include <QMutex>
00032
00033 #include "k3socketaddress.h"
00034 #include "k3resolver.h"
00035 #include "k3socketbase.h"
00036 #include "k3socketdevice.h"
00037 #include "k3bufferedsocket.h"
00038
00039 using namespace KNetwork;
00040
00041 class KNetwork::KServerSocketPrivate
00042 {
00043 public:
00044 KResolver resolver;
00045 KResolverResults resolverResults;
00046
00047 enum { None, LookupDone, Bound, Listening } state;
00048 int backlog;
00049 int timeout;
00050
00051 bool bindWhenFound : 1, listenWhenBound : 1, useKBufferedSocket : 1;
00052
00053 KServerSocketPrivate()
00054 : state(None), timeout(0), bindWhenFound(false), listenWhenBound(false),
00055 useKBufferedSocket(true)
00056 {
00057 resolver.setFlags(KResolver::Passive);
00058 resolver.setFamily(KResolver::KnownFamily);
00059 }
00060 };
00061
00062 KServerSocket::KServerSocket(QObject* parent)
00063 : QObject(parent), d(new KServerSocketPrivate)
00064 {
00065 QObject::connect(&d->resolver, SIGNAL(finished(const KNetwork::KResolverResults&)),
00066 this, SLOT(lookupFinishedSlot()));
00067 }
00068
00069 KServerSocket::KServerSocket(const QString& service, QObject* parent)
00070 : QObject(parent), d(new KServerSocketPrivate)
00071 {
00072 QObject::connect(&d->resolver, SIGNAL(finished(const KNetwork::KResolverResults&)),
00073 this, SLOT(lookupFinishedSlot()));
00074 d->resolver.setServiceName(service);
00075 }
00076
00077 KServerSocket::KServerSocket(const QString& node, const QString& service,
00078 QObject* parent)
00079 : QObject(parent), d(new KServerSocketPrivate)
00080 {
00081 QObject::connect(&d->resolver, SIGNAL(finished(const KNetwork::KResolverResults&)),
00082 this, SLOT(lookupFinishedSlot()));
00083 setAddress(node, service);
00084 }
00085
00086 KServerSocket::~KServerSocket()
00087 {
00088 close();
00089 delete d;
00090 }
00091
00092 bool KServerSocket::setSocketOptions(int opts)
00093 {
00094 QMutexLocker locker(mutex());
00095 KSocketBase::setSocketOptions(opts);
00096 bool result = socketDevice()->setSocketOptions(opts);
00097 copyError();
00098 return result;
00099 }
00100
00101 KResolver& KServerSocket::resolver() const
00102 {
00103 return d->resolver;
00104 }
00105
00106 const KResolverResults& KServerSocket::resolverResults() const
00107 {
00108 return d->resolverResults;
00109 }
00110
00111 void KServerSocket::setResolutionEnabled(bool enable)
00112 {
00113 if (enable)
00114 d->resolver.setFlags(d->resolver.flags() & ~KResolver::NoResolve);
00115 else
00116 d->resolver.setFlags(d->resolver.flags() | KResolver::NoResolve);
00117 }
00118
00119 void KServerSocket::setFamily(int families)
00120 {
00121 d->resolver.setFamily(families);
00122 }
00123
00124 void KServerSocket::setAddress(const QString& service)
00125 {
00126 d->resolver.setNodeName(QString());
00127 d->resolver.setServiceName(service);
00128 d->resolverResults.empty();
00129 if (d->state <= KServerSocketPrivate::LookupDone)
00130 d->state = KServerSocketPrivate::None;
00131 }
00132
00133 void KServerSocket::setAddress(const QString& node, const QString& service)
00134 {
00135 d->resolver.setNodeName(node);
00136 d->resolver.setServiceName(service);
00137 d->resolverResults.empty();
00138 if (d->state <= KServerSocketPrivate::LookupDone)
00139 d->state = KServerSocketPrivate::None;
00140 }
00141
00142 void KServerSocket::setTimeout(int msec)
00143 {
00144 d->timeout = msec;
00145 }
00146
00147 bool KServerSocket::lookup()
00148 {
00149 setError(NoError);
00150 if (d->resolver.isRunning() && !blocking())
00151 return true;
00152
00153 if (d->state >= KServerSocketPrivate::LookupDone)
00154 return true;
00155
00156
00157 if (d->resolver.serviceName().isNull() &&
00158 !d->resolver.nodeName().isNull())
00159 d->resolver.setServiceName(QLatin1String(""));
00160
00161
00162
00163
00164
00165 d->resolverResults = KResolverResults();
00166
00167 if (d->resolver.status() <= 0)
00168
00169 d->resolver.start();
00170
00171 if (blocking())
00172 {
00173
00174
00175
00176 d->resolver.wait();
00177
00178 }
00179
00180 return true;
00181 }
00182
00183 bool KServerSocket::bind(const KResolverEntry& address)
00184 {
00185 if (socketDevice()->bind(address))
00186 {
00187 setError(NoError);
00188
00189 d->state = KServerSocketPrivate::Bound;
00190 emit bound(address);
00191 return true;
00192 }
00193 copyError();
00194 return false;
00195 }
00196
00197 bool KServerSocket::bind(const QString& node, const QString& service)
00198 {
00199 setAddress(node, service);
00200 return bind();
00201 }
00202
00203 bool KServerSocket::bind(const QString& service)
00204 {
00205 setAddress(service);
00206 return bind();
00207 }
00208
00209 bool KServerSocket::bind()
00210 {
00211 if (d->state >= KServerSocketPrivate::Bound)
00212 return true;
00213
00214 if (d->state < KServerSocketPrivate::LookupDone)
00215 {
00216 if (!blocking())
00217 {
00218 d->bindWhenFound = true;
00219 bool ok = lookup();
00220 if (d->state >= KServerSocketPrivate::Bound)
00221 d->bindWhenFound = false;
00222 return ok;
00223 }
00224
00225
00226 if (!lookup())
00227 return false;
00228 }
00229
00230 return doBind();
00231 }
00232
00233 bool KServerSocket::listen(int backlog)
00234 {
00235
00236
00237
00238
00239
00240 if (d->state == KServerSocketPrivate::Listening)
00241 return true;
00242
00243 d->backlog = backlog;
00244
00245 if (d->state < KServerSocketPrivate::Bound)
00246 {
00247
00248
00249 d->listenWhenBound = true;
00250 if (!bind())
00251 {
00252 d->listenWhenBound = false;
00253 return false;
00254 }
00255
00256 if (d->state < KServerSocketPrivate::Bound)
00257
00258
00259 return true;
00260
00261 d->listenWhenBound = false;
00262 }
00263
00264 if (d->state < KServerSocketPrivate::Listening)
00265 return doListen();
00266
00267 return true;
00268 }
00269
00270 void KServerSocket::close()
00271 {
00272 socketDevice()->close();
00273 if (d->resolver.isRunning())
00274 d->resolver.cancel(false);
00275 d->state = KServerSocketPrivate::None;
00276 emit closed();
00277 }
00278
00279 void KServerSocket::setAcceptBuffered(bool enable)
00280 {
00281 d->useKBufferedSocket = enable;
00282 }
00283
00284 KStreamSocket* KServerSocket::accept()
00285 {
00286 if (d->state < KServerSocketPrivate::Listening)
00287 {
00288 if (!blocking())
00289 {
00290 listen();
00291 setError(WouldBlock);
00292 return NULL;
00293 }
00294 else if (!listen())
00295
00296 return false;
00297 }
00298
00299
00300 if (blocking() && d->timeout > 0)
00301 {
00302 bool timedout;
00303 if (!socketDevice()->poll(d->timeout, &timedout))
00304 {
00305 copyError();
00306 return NULL;
00307 }
00308
00309 if (timedout)
00310 return 0L;
00311 }
00312
00313
00314 KSocketDevice* accepted = socketDevice()->accept();
00315 if (!accepted)
00316 {
00317
00318 copyError();
00319 return NULL;
00320 }
00321
00322 KStreamSocket* streamsocket;
00323 if (d->useKBufferedSocket)
00324 {
00325 streamsocket = new KBufferedSocket();
00326 streamsocket->setOpenMode(KStreamSocket::ReadWrite);
00327 }
00328 else
00329 {
00330 streamsocket = new KStreamSocket();
00331 streamsocket->setOpenMode(KStreamSocket::ReadWrite |
00332 KStreamSocket::Unbuffered);
00333 }
00334 streamsocket->setSocketDevice(accepted);
00335
00336
00337
00338
00339 streamsocket->setState(KStreamSocket::Connected);
00340
00341 return streamsocket;
00342 }
00343
00344 KSocketAddress KServerSocket::localAddress() const
00345 {
00346 return socketDevice()->localAddress();
00347 }
00348
00349 KSocketAddress KServerSocket::externalAddress() const
00350 {
00351 return socketDevice()->externalAddress();
00352 }
00353
00354 void KServerSocket::lookupFinishedSlot()
00355 {
00356 if (d->resolver.isRunning() || d->state > KServerSocketPrivate::LookupDone)
00357 return;
00358
00359 if (d->resolver.status() < 0)
00360 {
00361 setError(LookupFailure);
00362 emit gotError(LookupFailure);
00363 d->bindWhenFound = d->listenWhenBound = false;
00364 d->state = KServerSocketPrivate::None;
00365 return;
00366 }
00367
00368
00369 d->resolverResults = d->resolver.results();
00370 d->state = KServerSocketPrivate::LookupDone;
00371 emit hostFound();
00372
00373 if (d->bindWhenFound)
00374 doBind();
00375 }
00376
00377 void KServerSocket::copyError()
00378 {
00379 setError(socketDevice()->error());
00380 }
00381
00382 bool KServerSocket::doBind()
00383 {
00384 d->bindWhenFound = false;
00385
00386
00387 KResolverResults::ConstIterator it = d->resolverResults.begin();
00388 for ( ; it != d->resolverResults.end(); ++it)
00389 if (bind(*it))
00390 {
00391 if (d->listenWhenBound)
00392 return doListen();
00393 return true;
00394 }
00395 else
00396 socketDevice()->close();
00397
00398
00399 emit gotError(error());
00400 return false;
00401 }
00402
00403 bool KServerSocket::doListen()
00404 {
00405 if (!socketDevice()->listen(d->backlog))
00406 {
00407 copyError();
00408 emit gotError(error());
00409 return false;
00410 }
00411
00412
00413 QObject::connect(socketDevice()->readNotifier(), SIGNAL(activated(int)),
00414 this, SIGNAL(readyAccept()));
00415 d->state = KServerSocketPrivate::Listening;
00416 return true;
00417 }
00418
00419
00420 #include "k3serversocket.moc"