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