kstreamsocket.cpp00001
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 (state() == Connected)
00164 return true;
00165
00166 if (remainingTimeout() <= 0)
00167 {
00168
00169 timeoutSlot();
00170 return false;
00171 }
00172
00173 if (socketDevice()->error() == InProgress)
00174 {
00175 bool timedout;
00176 socketDevice()->poll(remainingTimeout(), &timedout);
00177 if (timedout)
00178 {
00179 timeoutSlot();
00180 return false;
00181 }
00182 }
00183 }
00184 }
00185 }
00186
00187 connectionEvent();
00188 return error() == NoError;
00189 }
00190
00191 bool KStreamSocket::connect(const KResolverEntry& entry)
00192 {
00193 return KClientSocketBase::connect(entry);
00194 }
00195
00196 void KStreamSocket::hostFoundSlot()
00197 {
00198 QObject::disconnect(this, SLOT(hostFoundSlot()));
00199 if (timeout() > 0)
00200 d->timer.start(timeout(), true);
00201 QTimer::singleShot(0, this, SLOT(connectionEvent()));
00202 }
00203
00204 void KStreamSocket::connectionEvent()
00205 {
00206 if (state() != HostFound && state() != Connecting)
00207 return;
00208
00209 const KResolverResults& peer = peerResults();
00210 if (state() == HostFound)
00211 {
00212 d->startTime.start();
00213
00214 setState(Connecting);
00215 emit stateChanged(Connecting);
00216 d->peer = peer.begin();
00217 d->local = localResults().begin();
00218 }
00219
00220 while (d->peer != peer.end())
00221 {
00222 const KResolverEntry &r = *d->peer;
00223
00224 if (socketDevice()->socket() != -1)
00225 {
00226
00227
00228 if (socketDevice()->connect(r) && socketDevice()->error() == NoError)
00229 {
00230
00231 connectionSucceeded(r);
00232 return;
00233 }
00234 else if (socketDevice()->error() == InProgress)
00235
00236 return;
00237
00238
00239 copyError();
00240 socketDevice()->close();
00241 ++d->peer;
00242 continue;
00243 }
00244
00245
00246 if (!bindLocallyFor(r))
00247 {
00248
00249 ++d->peer;
00250 continue;
00251 }
00252
00253 {
00254 bool skip = false;
00255 emit aboutToConnect(r, skip);
00256 if (skip)
00257 {
00258 ++d->peer;
00259 continue;
00260 }
00261 }
00262
00263 if (socketDevice()->connect(r) || socketDevice()->error() == InProgress)
00264 {
00265
00266 if (socketDevice()->error() == InProgress)
00267 {
00268 QSocketNotifier *n = socketDevice()->readNotifier();
00269 QObject::connect(n, SIGNAL(activated(int)),
00270 this, SLOT(connectionEvent()));
00271 n->setEnabled(true);
00272
00273 n = socketDevice()->writeNotifier();
00274 QObject::connect(n, SIGNAL(activated(int)),
00275 this, SLOT(connectionEvent()));
00276 n->setEnabled(true);
00277
00278 return;
00279 }
00280
00281
00282 connectionSucceeded(r);
00283 return;
00284 }
00285
00286
00287
00288 copyError();
00289 socketDevice()->close();
00290 ++d->peer;
00291 }
00292
00293
00294 socketDevice()->setSocketOptions(socketOptions());
00295 setState(Idle);
00296 emit stateChanged(Idle);
00297 emit gotError(error());
00298 return;
00299 }
00300
00301 void KStreamSocket::timeoutSlot()
00302 {
00303 if (state() != Connecting)
00304 return;
00305
00306
00307 socketDevice()->close();
00308
00309 setError(IO_TimeOutError, Timeout);
00310 setState(HostFound);
00311 emit stateChanged(HostFound);
00312 emit gotError(Timeout);
00313 emit timedOut();
00314 }
00315
00316 bool KStreamSocket::bindLocallyFor(const KResolverEntry& peer)
00317 {
00318 const KResolverResults& local = localResults();
00319
00320 if (local.isEmpty())
00321
00322 return true;
00323
00324 bool foundone = false;
00325
00326 for (d->local = local.begin(); d->local != local.end(); ++d->local)
00327 if ((*d->local).family() == peer.family())
00328 {
00329
00330 foundone = true;
00331
00332 if (socketDevice()->bind(*d->local))
00333 return true;
00334 }
00335
00336 if (!foundone)
00337 {
00338
00339 setError(IO_BindError, NotSupported);
00340 emit gotError(NotSupported);
00341 }
00342 else
00343 copyError();
00344 return false;
00345 }
00346
00347 void KStreamSocket::connectionSucceeded(const KResolverEntry& peer)
00348 {
00349 QObject::disconnect(socketDevice()->readNotifier(), 0, this, SLOT(connectionEvent()));
00350 QObject::disconnect(socketDevice()->writeNotifier(), 0, this, SLOT(connectionEvent()));
00351
00352 resetError();
00353 setFlags(IO_Sequential | IO_Raw | IO_ReadWrite | IO_Open | IO_Async);
00354 setState(Connected);
00355 socketDevice()->setSocketOptions(socketOptions());
00356 d->timer.stop();
00357 emit stateChanged(Connected);
00358
00359 if (!localResults().isEmpty())
00360 emit bound(*d->local);
00361 emit connected(peer);
00362 }
00363
00364 #include "kstreamsocket.moc"
|