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