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