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 Q_LONG KClientSocketBase::bytesAvailable() const
00281 {
00282 return socketDevice()->bytesAvailable();
00283 }
00284
00285 Q_LONG KClientSocketBase::waitForMore(int msecs, bool *timeout)
00286 {
00287 return socketDevice()->waitForMore(msecs, timeout);
00288 }
00289
00290 Q_LONG KClientSocketBase::readBlock(char *data, Q_ULONG maxlen)
00291 {
00292 return socketDevice()->readBlock(data, maxlen);
00293 }
00294
00295 Q_LONG KClientSocketBase::readBlock(char *data, Q_ULONG maxlen, KSocketAddress& from)
00296 {
00297 return socketDevice()->readBlock(data, maxlen, from);
00298 }
00299
00300 Q_LONG KClientSocketBase::peekBlock(char *data, Q_ULONG maxlen)
00301 {
00302 return socketDevice()->peekBlock(data, maxlen);
00303 }
00304
00305 Q_LONG KClientSocketBase::peekBlock(char *data, Q_ULONG maxlen, KSocketAddress& from)
00306 {
00307 return socketDevice()->peekBlock(data, maxlen, from);
00308 }
00309
00310 Q_LONG KClientSocketBase::writeBlock(const char *data, Q_ULONG len)
00311 {
00312 return socketDevice()->writeBlock(data, len);
00313 }
00314
00315 Q_LONG KClientSocketBase::writeBlock(const char *data, Q_ULONG len, const KSocketAddress& to)
00316 {
00317 return socketDevice()->writeBlock(data, len, to);
00318 }
00319
00320 KSocketAddress KClientSocketBase::localAddress() const
00321 {
00322 return socketDevice()->localAddress();
00323 }
00324
00325 KSocketAddress KClientSocketBase::peerAddress() const
00326 {
00327 return socketDevice()->peerAddress();
00328 }
00329
00330 bool KClientSocketBase::emitsReadyRead() const
00331 {
00332 return d->enableRead;
00333 }
00334
00335 void KClientSocketBase::enableRead(bool enable)
00336 {
00337 QMutexLocker locker(mutex());
00338
00339 d->enableRead = enable;
00340 QSocketNotifier *n = socketDevice()->readNotifier();
00341 if (n)
00342 n->setEnabled(enable);
00343 }
00344
00345 bool KClientSocketBase::emitsReadyWrite() const
00346 {
00347 return d->enableWrite;
00348 }
00349
00350 void KClientSocketBase::enableWrite(bool enable)
00351 {
00352 QMutexLocker locker(mutex());
00353
00354 d->enableWrite = enable;
00355 QSocketNotifier *n = socketDevice()->writeNotifier();
00356 if (n)
00357 n->setEnabled(enable);
00358 }
00359
00360 void KClientSocketBase::slotReadActivity()
00361 {
00362 if (d->enableRead)
00363 emit readyRead();
00364 }
00365
00366 void KClientSocketBase::slotWriteActivity()
00367 {
00368 if (d->enableWrite)
00369 emit readyWrite();
00370 }
00371
00372 void KClientSocketBase::lookupFinishedSlot()
00373 {
00374 if (d->peerResolver.isRunning() || d->localResolver.isRunning() || state() != HostLookup)
00375 return;
00376
00377 QObject::disconnect(&d->peerResolver, 0L, this, SLOT(lookupFinishedSlot()));
00378 QObject::disconnect(&d->localResolver, 0L, this, SLOT(lookupFinishedSlot()));
00379 if (d->peerResolver.status() < 0 || d->localResolver.status() < 0)
00380 {
00381 setState(Idle);
00382 setError(IO_LookupError, LookupFailure);
00383 emit stateChanged(Idle);
00384 emit gotError(LookupFailure);
00385 return;
00386 }
00387
00388 d->localResults = d->localResolver.results();
00389 d->peerResults = d->peerResolver.results();
00390 setState(HostFound);
00391 emit stateChanged(HostFound);
00392 emit hostFound();
00393 }
00394
00395 void KClientSocketBase::stateChanging(SocketState newState)
00396 {
00397 if (newState == Connected && socketDevice())
00398 {
00399 QSocketNotifier *n = socketDevice()->readNotifier();
00400 if (n)
00401 {
00402 n->setEnabled(d->enableRead);
00403 QObject::connect(n, SIGNAL(activated(int)), this, SLOT(slotReadActivity()));
00404 }
00405 else
00406 return;
00407
00408 n = socketDevice()->writeNotifier();
00409 if (n)
00410 {
00411 n->setEnabled(d->enableWrite);
00412 QObject::connect(n, SIGNAL(activated(int)), this, SLOT(slotWriteActivity()));
00413 }
00414 else
00415 return;
00416 }
00417 }
00418
00419 void KClientSocketBase::copyError()
00420 {
00421 setError(socketDevice()->status(), socketDevice()->error());
00422 }
00423
00424 #include "kclientsocketbase.moc"