KDECore
k3clientsocketbase.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 "k3clientsocketbase.h"
00026
00027 #include <config.h>
00028 #include <config-network.h>
00029
00030 #include <QSocketNotifier>
00031 #include <QTimer>
00032 #include <QMutex>
00033
00034 #include "k3socketaddress.h"
00035 #include "k3resolver.h"
00036 #include "k3socketbase.h"
00037 #include "k3socketdevice.h"
00038
00039 using namespace KNetwork;
00040
00041 class KNetwork::KClientSocketBasePrivate
00042 {
00043 public:
00044 int state;
00045
00046 KResolver localResolver, peerResolver;
00047 KResolverResults localResults, peerResults;
00048
00049 bool enableRead : 1, enableWrite : 1;
00050 };
00051
00052 KClientSocketBase::KClientSocketBase(QObject *parent)
00053 : KActiveSocketBase(parent), d(new KClientSocketBasePrivate)
00054 {
00055 d->state = Idle;
00056 d->enableRead = true;
00057 d->enableWrite = false;
00058 }
00059
00060 KClientSocketBase::~KClientSocketBase()
00061 {
00062 close();
00063 delete d;
00064 }
00065
00066 KClientSocketBase::SocketState KClientSocketBase::state() const
00067 {
00068 return static_cast<SocketState>(d->state);
00069 }
00070
00071 void KClientSocketBase::setState(SocketState state)
00072 {
00073 d->state = state;
00074 stateChanging(state);
00075 }
00076
00077 bool KClientSocketBase::setSocketOptions(int opts)
00078 {
00079 QMutexLocker locker(mutex());
00080 KSocketBase::setSocketOptions(opts);
00081
00082
00083 if (hasDevice())
00084 {
00085 bool result = socketDevice()->setSocketOptions(opts);
00086 copyError();
00087 return result;
00088 }
00089
00090 return true;
00091 }
00092
00093 KResolver& KClientSocketBase::peerResolver() const
00094 {
00095 return d->peerResolver;
00096 }
00097
00098 const KResolverResults& KClientSocketBase::peerResults() const
00099 {
00100 return d->peerResults;
00101 }
00102
00103 KResolver& KClientSocketBase::localResolver() const
00104 {
00105 return d->localResolver;
00106 }
00107
00108 const KResolverResults& KClientSocketBase::localResults() const
00109 {
00110 return d->localResults;
00111 }
00112
00113 void KClientSocketBase::setResolutionEnabled(bool enable)
00114 {
00115 if (enable)
00116 {
00117 d->localResolver.setFlags(d->localResolver.flags() & ~KResolver::NoResolve);
00118 d->peerResolver.setFlags(d->peerResolver.flags() & ~KResolver::NoResolve);
00119 }
00120 else
00121 {
00122 d->localResolver.setFlags(d->localResolver.flags() | KResolver::NoResolve);
00123 d->peerResolver.setFlags(d->peerResolver.flags() | KResolver::NoResolve);
00124 }
00125 }
00126
00127 void KClientSocketBase::setFamily(int families)
00128 {
00129 d->localResolver.setFamily(families);
00130 d->peerResolver.setFamily(families);
00131 }
00132
00133 bool KClientSocketBase::lookup()
00134 {
00135 if (state() == HostLookup && !blocking())
00136 return true;
00137
00138 if (state() > HostLookup)
00139 return true;
00140
00141 if (state() < HostLookup)
00142 {
00143 if (d->localResolver.serviceName().isNull() &&
00144 !d->localResolver.nodeName().isNull())
00145 d->localResolver.setServiceName(QLatin1String(""));
00146
00147
00148
00149 QObject::connect(&d->peerResolver,
00150 SIGNAL(finished(const KNetwork::KResolverResults&)),
00151 this, SLOT(lookupFinishedSlot()));
00152 QObject::connect(&d->localResolver,
00153 SIGNAL(finished(const KNetwork::KResolverResults&)),
00154 this, SLOT(lookupFinishedSlot()));
00155
00156 if (d->localResolver.status() <= 0)
00157 d->localResolver.start();
00158 if (d->peerResolver.status() <= 0)
00159 d->peerResolver.start();
00160
00161 setState(HostLookup);
00162 emit stateChanged(HostLookup);
00163
00164 if (!d->localResolver.isRunning() && !d->peerResolver.isRunning())
00165 {
00166
00167
00168 if (blocking())
00169 lookupFinishedSlot();
00170 else
00171 QTimer::singleShot(0, this, SLOT(lookupFinishedSlot()));
00172 }
00173 else
00174 {
00175 d->localResults = d->peerResults = KResolverResults();
00176 }
00177 }
00178
00179 if (blocking())
00180 {
00181
00182
00183
00184 localResolver().wait();
00185 peerResolver().wait();
00186
00187
00188 }
00189
00190 return true;
00191 }
00192
00193 bool KClientSocketBase::bind(const KResolverEntry& address)
00194 {
00195 if (state() == HostLookup || state() > Connecting)
00196 return false;
00197
00198 if (socketDevice()->bind(address))
00199 {
00200 resetError();
00201
00202
00203 if (state() < Bound)
00204 {
00205 setState(Bound);
00206 emit stateChanged(Bound);
00207 emit bound(address);
00208 }
00209 return true;
00210 }
00211 return false;
00212 }
00213
00214 bool KClientSocketBase::connect(const KResolverEntry& address, OpenMode mode)
00215 {
00216 if (state() == Connected)
00217 return true;
00218 if (state() == HostLookup || state() > Connecting)
00219 return false;
00220
00221 bool ok = socketDevice()->connect(address);
00222 copyError();
00223
00224 if (ok)
00225 {
00226 SocketState newstate;
00227 if (error() == InProgress)
00228 newstate = Connecting;
00229 else
00230 newstate = Connected;
00231
00232 if (state() < newstate)
00233 {
00234 setState(newstate);
00235 emit stateChanged(newstate);
00236 if (error() == NoError)
00237 {
00238 KActiveSocketBase::open(mode | Unbuffered);
00239 emit connected(address);
00240 }
00241 }
00242
00243 return true;
00244 }
00245 return false;
00246 }
00247
00248 bool KClientSocketBase::disconnect()
00249 {
00250 if (state() != Connected)
00251 return false;
00252
00253 bool ok = socketDevice()->disconnect();
00254 copyError();
00255
00256 if (ok)
00257 {
00258 setState(Unconnected);
00259 emit stateChanged(Unconnected);
00260 return true;
00261 }
00262 return false;
00263 }
00264
00265 bool KClientSocketBase::open(OpenMode mode)
00266 {
00267 return connect(QString(), QString(), mode);
00268 }
00269
00270 void KClientSocketBase::close()
00271 {
00272 if (state() == Idle)
00273 return;
00274
00275 if (state() == HostLookup)
00276 {
00277 d->peerResolver.cancel(false);
00278 d->localResolver.cancel(false);
00279 }
00280
00281 d->localResults = d->peerResults = KResolverResults();
00282
00283 socketDevice()->close();
00284 KActiveSocketBase::close();
00285 setState(Idle);
00286 emit stateChanged(Idle);
00287 emit closed();
00288 }
00289
00290 bool KClientSocketBase::flush()
00291 {
00292 return false;
00293 }
00294
00295
00296 qint64 KClientSocketBase::bytesAvailable() const
00297 {
00298 return socketDevice()->bytesAvailable();
00299 }
00300
00301
00302
00303
00304 qint64 KClientSocketBase::waitForMore(int msecs, bool *timeout)
00305 {
00306 resetError();
00307 qint64 retval = socketDevice()->waitForMore(msecs, timeout);
00308 if (retval == -1)
00309 {
00310 copyError();
00311 emit gotError(error());
00312 }
00313 return retval;
00314 }
00315
00316 qint64 KClientSocketBase::readData(char *data, qint64 maxlen, KSocketAddress* from)
00317 {
00318 resetError();
00319 qint64 retval = socketDevice()->readData(data, maxlen, from);
00320 if (retval == -1)
00321 {
00322 copyError();
00323 emit gotError(error());
00324 }
00325 return retval;
00326 }
00327
00328 qint64 KClientSocketBase::peekData(char *data, qint64 maxlen, KSocketAddress* from)
00329 {
00330 resetError();
00331 qint64 retval = socketDevice()->peekData(data, maxlen, from);
00332 if (retval == -1)
00333 {
00334 copyError();
00335 emit gotError(error());
00336 }
00337 return retval;
00338 }
00339
00340 qint64 KClientSocketBase::writeData(const char *data, qint64 len, const KSocketAddress* to)
00341 {
00342 resetError();
00343 qint64 retval = socketDevice()->writeData(data, len, to);
00344 if (retval == -1)
00345 {
00346 copyError();
00347 emit gotError(error());
00348 }
00349 else
00350 emit bytesWritten(retval);
00351 return retval;
00352 }
00353
00354 KSocketAddress KClientSocketBase::localAddress() const
00355 {
00356 return socketDevice()->localAddress();
00357 }
00358
00359 KSocketAddress KClientSocketBase::peerAddress() const
00360 {
00361 return socketDevice()->peerAddress();
00362 }
00363
00364 bool KClientSocketBase::emitsReadyRead() const
00365 {
00366 return d->enableRead;
00367 }
00368
00369 void KClientSocketBase::enableRead(bool enable)
00370 {
00371 QMutexLocker locker(mutex());
00372
00373 d->enableRead = enable;
00374 QSocketNotifier *n = socketDevice()->readNotifier();
00375 if (n)
00376 n->setEnabled(enable);
00377 }
00378
00379 bool KClientSocketBase::emitsReadyWrite() const
00380 {
00381 return d->enableWrite;
00382 }
00383
00384 void KClientSocketBase::enableWrite(bool enable)
00385 {
00386 QMutexLocker locker(mutex());
00387
00388 d->enableWrite = enable;
00389 QSocketNotifier *n = socketDevice()->writeNotifier();
00390 if (n)
00391 n->setEnabled(enable);
00392 }
00393
00394 void KClientSocketBase::slotReadActivity()
00395 {
00396 if (d->enableRead)
00397 emit readyRead();
00398 }
00399
00400 void KClientSocketBase::slotWriteActivity()
00401 {
00402 if (d->enableWrite)
00403 emit readyWrite();
00404 }
00405
00406 void KClientSocketBase::lookupFinishedSlot()
00407 {
00408 if (d->peerResolver.isRunning() || d->localResolver.isRunning() || state() != HostLookup)
00409 return;
00410
00411 QObject::disconnect(&d->peerResolver, 0L, this, SLOT(lookupFinishedSlot()));
00412 QObject::disconnect(&d->localResolver, 0L, this, SLOT(lookupFinishedSlot()));
00413 if (d->peerResolver.status() < 0 || d->localResolver.status() < 0)
00414 {
00415 setState(Idle);
00416 setError(LookupFailure);
00417 emit stateChanged(Idle);
00418 emit gotError(LookupFailure);
00419 return;
00420 }
00421
00422 d->localResults = d->localResolver.results();
00423 d->peerResults = d->peerResolver.results();
00424 setState(HostFound);
00425 emit stateChanged(HostFound);
00426 emit hostFound();
00427 }
00428
00429 void KClientSocketBase::stateChanging(SocketState newState)
00430 {
00431 if (newState == Connected && socketDevice())
00432 {
00433 QSocketNotifier *n = socketDevice()->readNotifier();
00434 if (n)
00435 {
00436 n->setEnabled(d->enableRead);
00437 QObject::connect(n, SIGNAL(activated(int)), this, SLOT(slotReadActivity()));
00438 }
00439 else
00440 return;
00441
00442 n = socketDevice()->writeNotifier();
00443 if (n)
00444 {
00445 n->setEnabled(d->enableWrite);
00446 QObject::connect(n, SIGNAL(activated(int)), this, SLOT(slotWriteActivity()));
00447 }
00448 else
00449 return;
00450 }
00451 }
00452
00453 void KClientSocketBase::copyError()
00454 {
00455 setError(socketDevice()->error());
00456 }
00457
00458 #include "k3clientsocketbase.moc"