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"