kstreamsocket.cpp
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 <qdatetime.h>
00029 #include <qtimer.h>
00030
00031 #include "ksocketaddress.h"
00032 #include "kresolver.h"
00033 #include "ksocketdevice.h"
00034 #include "kstreamsocket.h"
00035
00036 using namespace KNetwork;
00037
00038 class KNetwork::KStreamSocketPrivate
00039 {
00040 public:
00041 KResolverResults::ConstIterator local, peer;
00042 QTime startTime;
00043 QTimer timer;
00044
00045 int timeout;
00046
00047 inline KStreamSocketPrivate()
00048 : timeout(0)
00049 { }
00050 };
00051
00052 KStreamSocket::KStreamSocket(const QString& node, const QString& service,
00053 QObject* parent, const char *name)
00054 : KClientSocketBase(parent, name), d(new KStreamSocketPrivate)
00055 {
00056 peerResolver().setNodeName(node);
00057 peerResolver().setServiceName(service);
00058 peerResolver().setFamily(KResolver::KnownFamily);
00059 localResolver().setFamily(KResolver::KnownFamily);
00060
00061 setSocketOptions(socketOptions() & ~Blocking);
00062
00063 QObject::connect(&d->timer, SIGNAL(timeout()), this, SLOT(timeoutSlot()));
00064 }
00065
00066 KStreamSocket::~KStreamSocket()
00067 {
00068 delete d;
00069
00070 }
00071
00072 int KStreamSocket::timeout() const
00073 {
00074 return d->timeout;
00075 }
00076
00077 int KStreamSocket::remainingTimeout() const
00078 {
00079 if (state() != Connecting)
00080 return timeout();
00081 if (timeout() <= 0)
00082 return 0;
00083
00084 return timeout() - d->startTime.elapsed();
00085 }
00086
00087 void KStreamSocket::setTimeout(int msecs)
00088 {
00089 d->timeout = msecs;
00090
00091 if (state() == Connecting)
00092 d->timer.changeInterval(msecs);
00093 }
00094
00095 bool KStreamSocket::bind(const QString& node, const QString& service)
00096 {
00097 if (state() != Idle)
00098 return false;
00099
00100 if (!node.isNull())
00101 localResolver().setNodeName(node);
00102 if (!service.isNull())
00103 localResolver().setServiceName(service);
00104 return true;
00105 }
00106
00107 bool KStreamSocket::connect(const QString& node, const QString& service)
00108 {
00109 if (state() == Connected)
00110 return true;
00111
00112 if (state() > Connected)
00113 return false;
00114
00115 if (!node.isNull())
00116 peerResolver().setNodeName(node);
00117 if (!service.isNull())
00118 peerResolver().setServiceName(service);
00119
00120 if (state() == Connecting && !blocking())
00121 {
00122 setError(IO_ConnectError, InProgress);
00123 emit gotError(InProgress);
00124 return true;
00125 }
00126
00127 if (state() < HostFound)
00128 {
00129
00130 if (!blocking())
00131 {
00132 QObject::connect(this, SIGNAL(hostFound()), SLOT(hostFoundSlot()));
00133 return lookup();
00134 }
00135
00136
00137 if (!lookup())
00138 return false;
00139 }
00140
00141
00142
00143
00144
00145 if (timeout() > 0)
00146 {
00147 if (!blocking() && !d->timer.isActive())
00148 d->timer.start(timeout(), true);
00149 else
00150 {
00151
00152
00153
00154
00155 d->timer.stop();
00156
00157 socketDevice()->setBlocking(false);
00158 while (true)
00159 {
00160 connectionEvent();
00161 if (state() < Connecting)
00162 return false;
00163 if (remainingTimeout() <= 0)
00164 {
00165
00166 timeoutSlot();
00167 return false;
00168 }
00169
00170 if (socketDevice()->error() == InProgress)
00171 {
00172 bool timedout;
00173 socketDevice()->poll(remainingTimeout(), &timedout);
00174 if (timedout)
00175 {
00176 timeoutSlot();
00177 return false;
00178 }
00179 }
00180 }
00181 }
00182 }
00183
00184 connectionEvent();
00185 return error() == NoError;
00186 }
00187
00188 bool KStreamSocket::connect(const KResolverEntry& entry)
00189 {
00190 return KClientSocketBase::connect(entry);
00191 }
00192
00193 void KStreamSocket::hostFoundSlot()
00194 {
00195 QObject::disconnect(this, SLOT(hostFoundSlot()));
00196 if (timeout() > 0)
00197 d->timer.start(timeout(), true);
00198 QTimer::singleShot(0, this, SLOT(connectionEvent()));
00199 }
00200
00201 void KStreamSocket::connectionEvent()
00202 {
00203 if (state() != HostFound && state() != Connecting)
00204 return;
00205
00206 const KResolverResults& peer = peerResults();
00207 if (state() == HostFound)
00208 {
00209 d->startTime.start();
00210
00211 setState(Connecting);
00212 emit stateChanged(Connecting);
00213 d->peer = peer.begin();
00214 d->local = localResults().begin();
00215 }
00216
00217 while (d->peer != peer.end())
00218 {
00219 const KResolverEntry &r = *d->peer;
00220
00221 if (socketDevice()->socket() != -1)
00222 {
00223
00224
00225 if (socketDevice()->connect(r) && socketDevice()->error() == NoError)
00226 {
00227
00228 connectionSucceeded(r);
00229 return;
00230 }
00231 else if (socketDevice()->error() == InProgress)
00232
00233 return;
00234
00235
00236 copyError();
00237 socketDevice()->close();
00238 ++d->peer;
00239 continue;
00240 }
00241
00242
00243 if (!bindLocallyFor(r))
00244 {
00245
00246 ++d->peer;
00247 continue;
00248 }
00249
00250 {
00251 bool skip = false;
00252 emit aboutToConnect(r, skip);
00253 if (skip)
00254 {
00255 ++d->peer;
00256 continue;
00257 }
00258 }
00259
00260 if (socketDevice()->connect(r) || socketDevice()->error() == InProgress)
00261 {
00262
00263 if (socketDevice()->error() == InProgress)
00264 {
00265 QSocketNotifier *n = socketDevice()->readNotifier();
00266 QObject::connect(n, SIGNAL(activated(int)),
00267 this, SLOT(connectionEvent()));
00268 n->setEnabled(true);
00269
00270 n = socketDevice()->writeNotifier();
00271 QObject::connect(n, SIGNAL(activated(int)),
00272 this, SLOT(connectionEvent()));
00273 n->setEnabled(true);
00274
00275 return;
00276 }
00277
00278
00279 continue;
00280 }
00281
00282
00283
00284 copyError();
00285 socketDevice()->close();
00286 ++d->peer;
00287 }
00288
00289
00290 setState(Idle);
00291 emit stateChanged(Idle);
00292 emit gotError(error());
00293 return;
00294 }
00295
00296 void KStreamSocket::timeoutSlot()
00297 {
00298 if (state() != Connecting)
00299 return;
00300
00301
00302 socketDevice()->close();
00303
00304 setError(IO_TimeOutError, Timeout);
00305 setState(HostFound);
00306 emit stateChanged(HostFound);
00307 emit gotError(Timeout);
00308 emit timedOut();
00309 }
00310
00311 bool KStreamSocket::bindLocallyFor(const KResolverEntry& peer)
00312 {
00313 const KResolverResults& local = localResults();
00314
00315 if (local.isEmpty())
00316
00317 return true;
00318
00319 bool foundone = false;
00320
00321 for (d->local = local.begin(); d->local != local.end(); ++d->local)
00322 if ((*d->local).family() == peer.family())
00323 {
00324
00325 foundone = true;
00326
00327 if (socketDevice()->bind(*d->local))
00328 return true;
00329 }
00330
00331 if (!foundone)
00332 {
00333
00334 setError(IO_BindError, NotSupported);
00335 emit gotError(NotSupported);
00336 }
00337 else
00338 copyError();
00339 return false;
00340 }
00341
00342 void KStreamSocket::connectionSucceeded(const KResolverEntry& peer)
00343 {
00344 QObject::disconnect(socketDevice()->readNotifier(), 0, this, SLOT(connectionEvent()));
00345 QObject::disconnect(socketDevice()->writeNotifier(), 0, this, SLOT(connectionEvent()));
00346
00347 resetError();
00348 setFlags(IO_Sequential | IO_Raw | IO_ReadWrite | IO_Open | IO_Async);
00349 setState(Connected);
00350 socketDevice()->setSocketOptions(socketOptions());
00351 d->timer.stop();
00352 emit stateChanged(Connected);
00353
00354 if (!localResults().isEmpty())
00355 emit bound(*d->local);
00356 emit connected(peer);
00357 }
00358
00359 #include "kstreamsocket.moc"
This file is part of the documentation for kdecore Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Sep 23 17:11:38 2004 by
doxygen 1.3.8-20040913 written by
Dimitri van Heesch, © 1997-2003