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