kclientsocketbase.cpp
/* -*- C++ -*-
* Copyright (C) 2003,2005 Thiago Macieira <thiago.macieira@kdemail.net>
*
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <config.h>
#include <qsocketnotifier.h>
#include <qtimer.h>
#include <qmutex.h>
#include "ksocketaddress.h"
#include "kresolver.h"
#include "ksocketbase.h"
#include "ksocketdevice.h"
#include "kclientsocketbase.h"
using namespace KNetwork;
class KNetwork::KClientSocketBasePrivate
{
public:
int state;
KResolver localResolver, peerResolver;
KResolverResults localResults, peerResults;
bool enableRead : 1, enableWrite : 1;
};
KClientSocketBase::KClientSocketBase(QObject *parent, const char *name)
: QObject(parent, name), d(new KClientSocketBasePrivate)
{
d->state = Idle;
d->enableRead = true;
d->enableWrite = false;
}
KClientSocketBase::~KClientSocketBase()
{
close();
delete d;
}
KClientSocketBase::SocketState KClientSocketBase::state() const
{
return static_cast<SocketState>(d->state);
}
void KClientSocketBase::setState(SocketState state)
{
d->state = state;
stateChanging(state);
}
bool KClientSocketBase::setSocketOptions(int opts)
{
QMutexLocker locker(mutex());
KSocketBase::setSocketOptions(opts); // call parent
// don't create the device unnecessarily
if (hasDevice())
{
bool result = socketDevice()->setSocketOptions(opts); // and set the implementation
copyError();
return result;
}
return true;
}
KResolver& KClientSocketBase::peerResolver() const
{
return d->peerResolver;
}
const KResolverResults& KClientSocketBase::peerResults() const
{
return d->peerResults;
}
KResolver& KClientSocketBase::localResolver() const
{
return d->localResolver;
}
const KResolverResults& KClientSocketBase::localResults() const
{
return d->localResults;
}
void KClientSocketBase::setResolutionEnabled(bool enable)
{
if (enable)
{
d->localResolver.setFlags(d->localResolver.flags() & ~KResolver::NoResolve);
d->peerResolver.setFlags(d->peerResolver.flags() & ~KResolver::NoResolve);
}
else
{
d->localResolver.setFlags(d->localResolver.flags() | KResolver::NoResolve);
d->peerResolver.setFlags(d->peerResolver.flags() | KResolver::NoResolve);
}
}
void KClientSocketBase::setFamily(int families)
{
d->localResolver.setFamily(families);
d->peerResolver.setFamily(families);
}
bool KClientSocketBase::lookup()
{
if (state() == HostLookup && !blocking())
return true; // already doing lookup
if (state() > HostLookup)
return true; // results are already available
if (state() < HostLookup)
{
if (d->localResolver.serviceName().isNull() &&
!d->localResolver.nodeName().isNull())
d->localResolver.setServiceName(QString::fromLatin1(""));
// don't restart the lookups if they had succeeded and
// the input values weren't changed
QObject::connect(&d->peerResolver, SIGNAL(finished(KResolverResults)),
this, SLOT(lookupFinishedSlot()));
QObject::connect(&d->localResolver, SIGNAL(finished(KResolverResults)),
this, SLOT(lookupFinishedSlot()));
if (d->localResolver.status() <= 0)
d->localResolver.start();
if (d->peerResolver.status() <= 0)
d->peerResolver.start();
setState(HostLookup);
emit stateChanged(HostLookup);
if (!d->localResolver.isRunning() && !d->peerResolver.isRunning())
{
// if nothing is running, then the lookup results are still valid
// pretend we had done lookup
if (blocking())
lookupFinishedSlot();
else
QTimer::singleShot(0, this, SLOT(lookupFinishedSlot()));
}
else
{
d->localResults = d->peerResults = KResolverResults();
}
}
if (blocking())
{
// we're in blocking mode operation
// wait for the results
localResolver().wait();
peerResolver().wait();
// lookupFinishedSlot has been called
}
return true;
}
bool KClientSocketBase::bind(const KResolverEntry& address)
{
if (state() == HostLookup || state() > Connecting)
return false;
if (socketDevice()->bind(address))
{
resetError();
// don't set the state or emit signals if we are in a higher state
if (state() < Bound)
{
setState(Bound);
emit stateChanged(Bound);
emit bound(address);
}
return true;
}
return false;
}
bool KClientSocketBase::connect(const KResolverEntry& address)
{
if (state() == Connected)
return true; // to be compliant with the other classes
if (state() == HostLookup || state() > Connecting)
return false;
bool ok = socketDevice()->connect(address);
copyError();
if (ok)
{
SocketState newstate;
if (error() == InProgress)
newstate = Connecting;
else
newstate = Connected;
if (state() < newstate)
{
setState(newstate);
emit stateChanged(newstate);
if (error() == NoError)
{
setFlags(IO_Sequential | IO_Raw | IO_ReadWrite | IO_Open | IO_Async);
emit connected(address);
}
}
return true;
}
return false;
}
bool KClientSocketBase::disconnect()
{
if (state() != Connected)
return false;
bool ok = socketDevice()->disconnect();
copyError();
if (ok)
{
setState(Unconnected);
emit stateChanged(Unconnected);
return true;
}
return false;
}
void KClientSocketBase::close()
{
if (state() == Idle)
return; // nothing to do
if (state() == HostLookup)
{
d->peerResolver.cancel(false);
d->localResolver.cancel(false);
}
d->localResults = d->peerResults = KResolverResults();
socketDevice()->close();
setState(Idle);
emit stateChanged(Idle);
emit closed();
}
// This function is unlike all the others because it is const
Q_LONG KClientSocketBase::bytesAvailable() const
{
return socketDevice()->bytesAvailable();
}
// All the functions below look really alike
// Should I use a macro to define them?
Q_LONG KClientSocketBase::waitForMore(int msecs, bool *timeout)
{
resetError();
Q_LONG retval = socketDevice()->waitForMore(msecs, timeout);
if (retval == -1)
{
copyError();
emit gotError(error());
}
return retval;
}
Q_LONG KClientSocketBase::readBlock(char *data, Q_ULONG maxlen)
{
resetError();
Q_LONG retval = socketDevice()->readBlock(data, maxlen);
if (retval == -1)
{
copyError();
emit gotError(error());
}
return retval;
}
Q_LONG KClientSocketBase::readBlock(char *data, Q_ULONG maxlen, KSocketAddress& from)
{
resetError();
Q_LONG retval = socketDevice()->readBlock(data, maxlen, from);
if (retval == -1)
{
copyError();
emit gotError(error());
}
return retval;
}
Q_LONG KClientSocketBase::peekBlock(char *data, Q_ULONG maxlen)
{
resetError();
Q_LONG retval = socketDevice()->peekBlock(data, maxlen);
if (retval == -1)
{
copyError();
emit gotError(error());
}
return retval;
}
Q_LONG KClientSocketBase::peekBlock(char *data, Q_ULONG maxlen, KSocketAddress& from)
{
resetError();
Q_LONG retval = socketDevice()->peekBlock(data, maxlen, from);
if (retval == -1)
{
copyError();
emit gotError(error());
}
return retval;
}
Q_LONG KClientSocketBase::writeBlock(const char *data, Q_ULONG len)
{
resetError();
Q_LONG retval = socketDevice()->writeBlock(data, len);
if (retval == -1)
{
copyError();
emit gotError(error());
}
return retval;
}
Q_LONG KClientSocketBase::writeBlock(const char *data, Q_ULONG len, const KSocketAddress& to)
{
resetError();
Q_LONG retval = socketDevice()->writeBlock(data, len, to);
if (retval == -1)
{
copyError();
emit gotError(error());
}
return retval;
}
KSocketAddress KClientSocketBase::localAddress() const
{
return socketDevice()->localAddress();
}
KSocketAddress KClientSocketBase::peerAddress() const
{
return socketDevice()->peerAddress();
}
bool KClientSocketBase::emitsReadyRead() const
{
return d->enableRead;
}
void KClientSocketBase::enableRead(bool enable)
{
QMutexLocker locker(mutex());
d->enableRead = enable;
QSocketNotifier *n = socketDevice()->readNotifier();
if (n)
n->setEnabled(enable);
}
bool KClientSocketBase::emitsReadyWrite() const
{
return d->enableWrite;
}
void KClientSocketBase::enableWrite(bool enable)
{
QMutexLocker locker(mutex());
d->enableWrite = enable;
QSocketNotifier *n = socketDevice()->writeNotifier();
if (n)
n->setEnabled(enable);
}
void KClientSocketBase::slotReadActivity()
{
if (d->enableRead)
emit readyRead();
}
void KClientSocketBase::slotWriteActivity()
{
if (d->enableWrite)
emit readyWrite();
}
void KClientSocketBase::lookupFinishedSlot()
{
if (d->peerResolver.isRunning() || d->localResolver.isRunning() || state() != HostLookup)
return;
QObject::disconnect(&d->peerResolver, 0L, this, SLOT(lookupFinishedSlot()));
QObject::disconnect(&d->localResolver, 0L, this, SLOT(lookupFinishedSlot()));
if (d->peerResolver.status() < 0 || d->localResolver.status() < 0)
{
setState(Idle); // backtrack
setError(IO_LookupError, LookupFailure);
emit stateChanged(Idle);
emit gotError(LookupFailure);
return;
}
d->localResults = d->localResolver.results();
d->peerResults = d->peerResolver.results();
setState(HostFound);
emit stateChanged(HostFound);
emit hostFound();
}
void KClientSocketBase::stateChanging(SocketState newState)
{
if (newState == Connected && socketDevice())
{
QSocketNotifier *n = socketDevice()->readNotifier();
if (n)
{
n->setEnabled(d->enableRead);
QObject::connect(n, SIGNAL(activated(int)), this, SLOT(slotReadActivity()));
}
else
return;
n = socketDevice()->writeNotifier();
if (n)
{
n->setEnabled(d->enableWrite);
QObject::connect(n, SIGNAL(activated(int)), this, SLOT(slotWriteActivity()));
}
else
return;
}
}
void KClientSocketBase::copyError()
{
setError(socketDevice()->status(), socketDevice()->error());
}
#include "kclientsocketbase.moc"
KNetwork::KSocketBase::blocking
bool blocking() const
Retrieves this socket's blocking mode.
Definition: ksocketbase.cpp:81
KNetwork::KSocketBase::socketDevice
KSocketDevice * socketDevice() const
Retrieves the socket implementation used on this socket.
Definition: ksocketbase.cpp:116
KNetwork::KClientSocketBase::state
SocketState state() const
Returns the current state for this socket.
Definition: kclientsocketbase.cpp:64
KNetwork::KClientSocketBase::waitForMore
virtual Q_LONG waitForMore(int msecs, bool *timeout=0L)
Waits for more data.
Definition: kclientsocketbase.cpp:289
KNetwork::KClientSocketBase::writeBlock
virtual Q_LONG writeBlock(const char *data, Q_ULONG len)
Writes data to the socket.
Definition: kclientsocketbase.cpp:349
KNetwork::KResolverEntry
One resolution entry.
Definition: kresolver.h:66
KNetwork::KActiveSocketBase::resetError
void resetError()
Resets the socket error code and the I/O Device's status.
Definition: ksocketbase.cpp:315
KNetwork::KSocketDevice::writeNotifier
QSocketNotifier * writeNotifier() const
Returns a socket notifier for output on this socket.
Definition: ksocketdevice.cpp:627
KNetwork::KResolver
Name and service resolution class.
Definition: kresolver.h:295
KNetwork::KClientSocketBase::lookup
virtual bool lookup()
Starts the lookup for peer and local hostnames as well as their services.
Definition: kclientsocketbase.cpp:131
KNetwork::KClientSocketBase::localResolver
KResolver & localResolver() const
Returns the internal KResolver object used for looking up the local host name and service...
Definition: kclientsocketbase.cpp:101
KNetwork::KClientSocketBase::slotReadActivity
virtual void slotReadActivity()
This slot is connected to the read notifier's signal meaning the socket can read more data...
Definition: kclientsocketbase.cpp:413
KNetwork::KSocketBase::error
SocketError error() const
Retrieves the socket error code.
Definition: ksocketbase.cpp:160
KNetwork::KClientSocketBase::KClientSocketBase
KClientSocketBase(QObject *parent, const char *name)
Default constructor.
Definition: kclientsocketbase.cpp:50
KNetwork::KSocketAddress
A generic socket address.
Definition: ksocketaddress.h:423
KNetwork::KClientSocketBase::gotError
void gotError(int code)
This signal is emitted when this object finds an error.
KNetwork::KClientSocketBase::hostFound
void hostFound()
This signal is emitted when the lookup is successfully completed.
KNetwork::KResolverResults
Name and service resolution results.
Definition: kresolver.h:197
KNetwork::KSocketDevice::setSocketOptions
virtual bool setSocketOptions(int opts)
This implementation sets the options on the socket.
Definition: ksocketdevice.cpp:110
KNetwork::KClientSocketBase::setSocketOptions
virtual bool setSocketOptions(int opts)
Sets the socket options.
Definition: kclientsocketbase.cpp:75
KNetwork::KClientSocketBase::connect
virtual bool connect(const QString &node=QString::null, const QString &service=QString::null)=0
Attempts to connect to the these hostname and service, or use the default ones if none are given...
KNetwork::KSocketDevice::readNotifier
QSocketNotifier * readNotifier() const
Returns a socket notifier for input on this socket.
Definition: ksocketdevice.cpp:609
KNetwork::KClientSocketBase::copyError
void copyError()
Convenience function to set this object's error code to match that of the socket device.
Definition: kclientsocketbase.cpp:472
KNetwork::KSocketDevice::writeBlock
virtual Q_LONG writeBlock(const char *data, Q_ULONG len)
Writes data to the socket.
Definition: ksocketdevice.cpp:501
KNetwork::KClientSocketBase::setResolutionEnabled
void setResolutionEnabled(bool enable)
Enables or disables name resolution.
Definition: kclientsocketbase.cpp:111
KNetwork::KSocketDevice::bytesAvailable
virtual Q_LONG bytesAvailable() const
Returns the number of bytes available for reading without blocking.
Definition: ksocketdevice.cpp:367
KNetwork::KResolver::wait
bool wait(int msec=0)
Waits for a request to finish resolving.
Definition: kresolver.cpp:457
KNetwork::KClientSocketBase::peerAddress
virtual KSocketAddress peerAddress() const
Returns the peer socket address.
Definition: kclientsocketbase.cpp:378
KNetwork::KClientSocketBase::peekBlock
virtual Q_LONG peekBlock(char *data, Q_ULONG maxlen)
Peeks data from the socket.
Definition: kclientsocketbase.cpp:325
KNetwork::KSocketBase::mutex
QMutex * mutex() const
Returns the internal mutex for this class.
Definition: ksocketbase.cpp:278
KNetwork::KActiveSocketBase::setError
void setError(int status, SocketError error)
Sets the socket's error code and the I/O Device's status.
Definition: ksocketbase.cpp:309
KNetwork::KClientSocketBase::peerResults
const KResolverResults & peerResults() const
Returns the internal list of resolved results for the peer address.
Definition: kclientsocketbase.cpp:96
KNetwork::KClientSocketBase::SocketState
SocketState
Socket states.
Definition: kclientsocketbase.h:71
KNetwork::KClientSocketBase::connected
void connected(const KResolverEntry &remote)
This socket is emitted when the socket successfully connects to a remote address. ...
KNetwork::KClientSocketBase::readBlock
virtual Q_LONG readBlock(char *data, Q_ULONG maxlen)
Reads data from a socket.
Definition: kclientsocketbase.cpp:301
KNetwork::KClientSocketBase::setState
void setState(SocketState state)
Sets the socket state to state.
Definition: kclientsocketbase.cpp:69
KNetwork::KClientSocketBase::readyRead
void readyRead()
This signal is emitted whenever the socket is ready for reading – i.e., there is data to be read in ...
KNetwork::KSocketBase::setSocketOptions
virtual bool setSocketOptions(int opts)
Set the given socket options.
Definition: ksocketbase.cpp:65
KNetwork::KClientSocketBase::stateChanged
void stateChanged(int newstate)
This signal is emitted whenever the socket state changes.
KNetwork::KClientSocketBase::readyWrite
void readyWrite()
This signal is emitted whenever the socket is ready for writing – i.e., whenever there's space avail...
KNetwork::KSocketDevice::peekBlock
virtual Q_LONG peekBlock(char *data, Q_ULONG maxlen)
Peeks data in the socket.
Definition: ksocketdevice.cpp:459
KNetwork::KSocketDevice::disconnect
virtual bool disconnect()
Disconnects this socket.
Definition: ksocketdevice.cpp:333
KNetwork::KSocketDevice::connect
virtual bool connect(const KResolverEntry &address)
Connect to a remote host.
Definition: ksocketdevice.cpp:276
KNetwork::KClientSocketBase::localAddress
virtual KSocketAddress localAddress() const
Returns the local socket address.
Definition: kclientsocketbase.cpp:373
KNetwork::KClientSocketBase::disconnect
virtual bool disconnect()
Disconnects the socket.
Definition: kclientsocketbase.cpp:244
KNetwork::KClientSocketBase::bound
void bound(const KResolverEntry &local)
This signal is emitted when the socket successfully binds to an address.
KNetwork::KSocketDevice::close
virtual void close()
Closes the socket.
Definition: ksocketdevice.cpp:180
KNetwork::KClientSocketBase::enableRead
virtual void enableRead(bool enable)
Enables the emission of the readyRead signal.
Definition: kclientsocketbase.cpp:388
KNetwork::KClientSocketBase::bytesAvailable
virtual Q_LONG bytesAvailable() const
Returns the number of bytes available on this socket.
Definition: kclientsocketbase.cpp:281
KNetwork::KClientSocketBase::close
virtual void close()
Closes the socket.
Definition: kclientsocketbase.cpp:261
KNetwork::KClientSocketBase::~KClientSocketBase
virtual ~KClientSocketBase()
Destructor.
Definition: kclientsocketbase.cpp:58
KNetwork::KSocketDevice::localAddress
virtual KSocketAddress localAddress() const
Returns this socket's local address.
Definition: ksocketdevice.cpp:530
KNetwork::KSocketDevice::peerAddress
virtual KSocketAddress peerAddress() const
Returns this socket's peer address.
Definition: ksocketdevice.cpp:566
KNetwork::KSocketDevice::readBlock
virtual Q_LONG readBlock(char *data, Q_ULONG maxlen)
Reads data from this socket.
Definition: ksocketdevice.cpp:417
KNetwork::KClientSocketBase::stateChanging
virtual void stateChanging(SocketState newState)
This function is called by setState whenever the state changes.
Definition: kclientsocketbase.cpp:448
KNetwork::KClientSocketBase::setFamily
void setFamily(int families)
Sets the allowed families for the resolutions.
Definition: kclientsocketbase.cpp:125
KNetwork::KSocketBase::hasDevice
bool hasDevice() const
Returns true if the socket device has been initialised in this object, either by calling socketDevice...
Definition: ksocketbase.cpp:150
KNetwork::KClientSocketBase::emitsReadyRead
bool emitsReadyRead() const
Returns true if the readyRead signal is set to be emitted.
Definition: kclientsocketbase.cpp:383
KNetwork::KClientSocketBase::localResults
const KResolverResults & localResults() const
Returns the internal list of resolved results for the local address.
Definition: kclientsocketbase.cpp:106
KNetwork::KClientSocketBase::bind
virtual bool bind(const QString &node=QString::null, const QString &service=QString::null)=0
Binds this socket to the given nodename and service, or use the default ones if none are given...
KNetwork::KClientSocketBase::emitsReadyWrite
bool emitsReadyWrite() const
Returns true if the readyWrite signal is set to be emitted.
Definition: kclientsocketbase.cpp:398
KNetwork::KSocketDevice::waitForMore
virtual Q_LONG waitForMore(int msecs, bool *timeout=0L)
Waits up to msecs for more data to be available on this socket.
Definition: ksocketdevice.cpp:379
KNetwork::KClientSocketBase::peerResolver
KResolver & peerResolver() const
Returns the internal KResolver object used for looking up the peer host name and service.
Definition: kclientsocketbase.cpp:91
KNetwork::KClientSocketBase::enableWrite
virtual void enableWrite(bool enable)
Enables the emission of the readyWrite signal.
Definition: kclientsocketbase.cpp:403
KNetwork::KClientSocketBase::closed
void closed()
This signal is emitted when the socket completes the closing/shut down process.
KNetwork::KClientSocketBase::slotWriteActivity
virtual void slotWriteActivity()
This slot is connected to the write notifier's signal meaning the socket can write more data...
Definition: kclientsocketbase.cpp:419

KDE Home | KDE Accessibility Home | Description of Access Keys