• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdecore
 

tdecore

kclientsocketbase.cpp
00001 /*  -*- C++ -*-
00002  *  Copyright (C) 2003,2005 Thiago Macieira <thiago.macieira@kdemail.net>
00003  *
00004  *
00005  *  Permission is hereby granted, free of charge, to any person obtaining
00006  *  a copy of this software and associated documentation files (the
00007  *  "Software"), to deal in the Software without restriction, including
00008  *  without limitation the rights to use, copy, modify, merge, publish,
00009  *  distribute, sublicense, and/or sell copies of the Software, and to
00010  *  permit persons to whom the Software is furnished to do so, subject to
00011  *  the following conditions:
00012  *
00013  *  The above copyright notice and this permission notice shall be included 
00014  *  in all copies or substantial portions of the Software.
00015  *
00016  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00017  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00018  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00019  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00020  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00021  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00022  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00023  */
00024 
00025 #include <config.h>
00026 
00027 #include <tqsocketnotifier.h>
00028 #include <tqtimer.h>
00029 #include <tqmutex.h>
00030 
00031 #include "tdesocketaddress.h"
00032 #include "kresolver.h"
00033 #include "tdesocketbase.h"
00034 #include "tdesocketdevice.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(TQObject *parent, const char *name)  :
00051 #ifdef USE_QT4
00052 #else // USE_QT4
00053     TQObject(parent, name),
00054 #endif // USE_QT4
00055     d(new KClientSocketBasePrivate)
00056 {
00057 #ifdef USE_QT4
00058   setParent(parent);
00059   setObjectName(name);
00060 #endif // USE_QT4
00061   d->state = Idle;
00062   d->enableRead = true;
00063   d->enableWrite = false;
00064 }
00065 
00066 KClientSocketBase::~KClientSocketBase()
00067 {
00068   close();
00069   delete d;
00070 }
00071 
00072 KClientSocketBase::SocketState KClientSocketBase::state() const
00073 {
00074   return static_cast<SocketState>(d->state);
00075 }
00076 
00077 void KClientSocketBase::setState(SocketState state)
00078 {
00079   d->state = state;
00080   stateChanging(state);
00081 }
00082 
00083 bool KClientSocketBase::setSocketOptions(int opts)
00084 {
00085   TQMutexLocker locker(mutex());
00086   TDESocketBase::setSocketOptions(opts); // call parent
00087 
00088   // don't create the device unnecessarily
00089   if (hasDevice())
00090     {
00091       bool result = socketDevice()->setSocketOptions(opts); // and set the implementation
00092       copyError();
00093       return result;
00094     }
00095 
00096   return true;
00097 }
00098 
00099 KResolver& KClientSocketBase::peerResolver() const
00100 {
00101   return d->peerResolver;
00102 }
00103 
00104 const KResolverResults& KClientSocketBase::peerResults() const
00105 {
00106   return d->peerResults;
00107 }
00108 
00109 KResolver& KClientSocketBase::localResolver() const
00110 {
00111   return d->localResolver;
00112 }
00113 
00114 const KResolverResults& KClientSocketBase::localResults() const
00115 {
00116   return d->localResults;
00117 }
00118 
00119 void KClientSocketBase::setResolutionEnabled(bool enable)
00120 {
00121   if (enable)
00122     {
00123       d->localResolver.setFlags(d->localResolver.flags() & ~KResolver::NoResolve);
00124       d->peerResolver.setFlags(d->peerResolver.flags() & ~KResolver::NoResolve);
00125     }
00126   else
00127     {
00128       d->localResolver.setFlags(d->localResolver.flags() | KResolver::NoResolve);
00129       d->peerResolver.setFlags(d->peerResolver.flags() | KResolver::NoResolve);
00130     }
00131 }
00132 
00133 void KClientSocketBase::setFamily(int families)
00134 {
00135   d->localResolver.setFamily(families);
00136   d->peerResolver.setFamily(families);
00137 }
00138 
00139 bool KClientSocketBase::lookup()
00140 {
00141   if (state() == HostLookup && !blocking())
00142     return true;        // already doing lookup
00143 
00144   if (state() > HostLookup)
00145     return true;        // results are already available
00146 
00147   if (state() < HostLookup)
00148     {
00149       if (d->localResolver.serviceName().isNull() &&
00150       !d->localResolver.nodeName().isNull())
00151     d->localResolver.setServiceName(TQString::fromLatin1(""));
00152 
00153       // don't restart the lookups if they had succeeded and
00154       // the input values weren't changed
00155       TQObject::connect(&d->peerResolver, TQT_SIGNAL(finished(KResolverResults)), 
00156                this, TQT_SLOT(lookupFinishedSlot()));
00157       TQObject::connect(&d->localResolver, TQT_SIGNAL(finished(KResolverResults)), 
00158                this, TQT_SLOT(lookupFinishedSlot()));
00159 
00160       if (d->localResolver.status() <= 0)
00161     d->localResolver.start();
00162       if (d->peerResolver.status() <= 0)
00163     d->peerResolver.start();
00164 
00165       setState(HostLookup);
00166       emit stateChanged(HostLookup);
00167 
00168       if (!d->localResolver.isRunning() && !d->peerResolver.isRunning())
00169     {
00170       // if nothing is running, then the lookup results are still valid
00171       // pretend we had done lookup
00172       if (blocking())
00173         lookupFinishedSlot();
00174       else
00175         TQTimer::singleShot(0, this, TQT_SLOT(lookupFinishedSlot()));
00176     }
00177       else
00178     {
00179       d->localResults = d->peerResults = KResolverResults();
00180     }
00181     }
00182 
00183   if (blocking())
00184     {
00185       // we're in blocking mode operation
00186       // wait for the results
00187 
00188       localResolver().wait();
00189       peerResolver().wait();
00190 
00191       // lookupFinishedSlot has been called
00192     }
00193 
00194   return true;
00195 }
00196 
00197 bool KClientSocketBase::bind(const KResolverEntry& address)
00198 {
00199   if (state() == HostLookup || state() > Connecting)
00200     return false;
00201 
00202   if (socketDevice()->bind(address))
00203     {
00204       resetError();
00205 
00206       // don't set the state or emit signals if we are in a higher state
00207       if (state() < Bound)
00208     {
00209       setState(Bound);
00210       emit stateChanged(Bound);
00211       emit bound(address);
00212     }
00213       return true;
00214     }
00215   return false;
00216 }
00217 
00218 bool KClientSocketBase::connect(const KResolverEntry& address)
00219 {
00220   if (state() == Connected)
00221     return true;        // to be compliant with the other classes
00222   if (state() == HostLookup || state() > Connecting)
00223     return false;
00224 
00225   bool ok = socketDevice()->connect(address);
00226   copyError();
00227 
00228   if (ok)
00229     {
00230       SocketState newstate;
00231       if (error() == InProgress)
00232     newstate = Connecting;
00233       else
00234     newstate = Connected;
00235 
00236       if (state() < newstate)
00237     {
00238       setState(newstate);
00239       emit stateChanged(newstate);
00240       if (error() == NoError)
00241         {
00242           setFlags(IO_Sequential | IO_Raw | IO_ReadWrite | IO_Open | IO_Async);
00243           emit connected(address);
00244         }
00245     }
00246 
00247       return true;
00248     }
00249   return false;
00250 }
00251 
00252 bool KClientSocketBase::disconnect()
00253 {
00254   if (state() != Connected)
00255     return false;
00256 
00257   bool ok = socketDevice()->disconnect();
00258   copyError();
00259 
00260   if (ok)
00261     {
00262       setState(Unconnected);
00263       emit stateChanged(Unconnected);
00264       return true;
00265     }
00266   return false;
00267 }
00268 
00269 void KClientSocketBase::close()
00270 {
00271   if (state() == Idle)
00272     return;             // nothing to do
00273 
00274   if (state() == HostLookup)
00275     {
00276       d->peerResolver.cancel(false);
00277       d->localResolver.cancel(false);
00278     }
00279 
00280   d->localResults = d->peerResults = KResolverResults();
00281 
00282   socketDevice()->close();
00283   setState(Idle);
00284   emit stateChanged(Idle);
00285   emit closed();
00286 }
00287 
00288 // This function is unlike all the others because it is const
00289 #ifdef USE_QT3
00290 TQ_LONG KClientSocketBase::bytesAvailable() const
00291 #endif
00292 #ifdef USE_QT4
00293 qint64 KClientSocketBase::bytesAvailable() const
00294 #endif
00295 {
00296   return socketDevice()->bytesAvailable();
00297 }
00298 
00299 // All the functions below look really alike
00300 // Should I use a macro to define them?
00301 
00302 TQ_LONG KClientSocketBase::waitForMore(int msecs, bool *timeout)
00303 {
00304   resetError();
00305   TQ_LONG retval = socketDevice()->waitForMore(msecs, timeout);
00306   if (retval == -1)
00307     {
00308       copyError();
00309       emit gotError(error());
00310     }
00311   return retval;
00312 }
00313 
00314 TQT_TQIO_LONG KClientSocketBase::tqreadBlock(char *data, TQT_TQIO_ULONG maxlen)
00315 {
00316   resetError();
00317   TQ_LONG retval = socketDevice()->tqreadBlock(data, maxlen);
00318   if (retval == -1)
00319     {
00320       copyError();
00321       emit gotError(error());
00322     }
00323   return retval;
00324 }
00325 
00326 TQT_TQIO_LONG KClientSocketBase::tqreadBlock(char *data, TQT_TQIO_ULONG maxlen, TDESocketAddress& from)
00327 {
00328   resetError();
00329   TQ_LONG retval = socketDevice()->tqreadBlock(data, maxlen, from);
00330   if (retval == -1)
00331     {
00332       copyError();
00333       emit gotError(error());
00334     }
00335   return retval;
00336 }
00337 
00338 TQ_LONG KClientSocketBase::peekBlock(char *data, TQ_ULONG maxlen)
00339 {
00340   resetError();
00341   TQ_LONG retval = socketDevice()->peekBlock(data, maxlen);
00342   if (retval == -1)
00343     {
00344       copyError();
00345       emit gotError(error());
00346     }
00347   return retval;
00348 }
00349 
00350 TQ_LONG KClientSocketBase::peekBlock(char *data, TQ_ULONG maxlen, TDESocketAddress& from)
00351 {
00352   resetError();
00353   TQ_LONG retval = socketDevice()->peekBlock(data, maxlen, from);
00354   if (retval == -1)
00355     {
00356       copyError();
00357       emit gotError(error());
00358     }
00359   return retval;
00360 }
00361 
00362 TQT_TQIO_LONG KClientSocketBase::tqwriteBlock(const char *data, TQT_TQIO_ULONG len)
00363 {
00364   resetError();
00365   TQ_LONG retval = socketDevice()->tqwriteBlock(data, len);
00366   if (retval == -1)
00367     {
00368       copyError();
00369       emit gotError(error());
00370     }
00371   return retval;
00372 }
00373 
00374 TQT_TQIO_LONG KClientSocketBase::tqwriteBlock(const char *data, TQT_TQIO_ULONG len, const TDESocketAddress& to)
00375 {
00376   resetError();
00377   TQ_LONG retval = socketDevice()->tqwriteBlock(data, len, to);
00378   if (retval == -1)
00379     {
00380       copyError();
00381       emit gotError(error());
00382     }
00383   return retval;
00384 }
00385 
00386 TDESocketAddress KClientSocketBase::localAddress() const
00387 {
00388   return socketDevice()->localAddress();
00389 }
00390 
00391 TDESocketAddress KClientSocketBase::peerAddress() const
00392 {
00393   return socketDevice()->peerAddress();
00394 }
00395 
00396 bool KClientSocketBase::emitsReadyRead() const
00397 {
00398   return d->enableRead;
00399 }
00400 
00401 void KClientSocketBase::enableRead(bool enable)
00402 {
00403   TQMutexLocker locker(mutex());
00404 
00405   d->enableRead = enable;
00406   TQSocketNotifier *n = socketDevice()->readNotifier();
00407   if (n)
00408     n->setEnabled(enable);
00409 }
00410 
00411 bool KClientSocketBase::emitsReadyWrite() const
00412 {
00413   return d->enableWrite;
00414 }
00415 
00416 void KClientSocketBase::enableWrite(bool enable)
00417 {
00418   TQMutexLocker locker(mutex());
00419 
00420   d->enableWrite = enable;
00421   TQSocketNotifier *n = socketDevice()->writeNotifier();
00422   if (n)
00423     n->setEnabled(enable);
00424 }
00425 
00426 void KClientSocketBase::slotReadActivity()
00427 {
00428   if (d->enableRead)
00429     emit readyRead();
00430 }
00431 
00432 void KClientSocketBase::slotWriteActivity()
00433 {
00434   if (d->enableWrite)
00435     emit readyWrite();
00436 }
00437 
00438 void KClientSocketBase::lookupFinishedSlot()
00439 {
00440   if (d->peerResolver.isRunning() || d->localResolver.isRunning() || state() != HostLookup)
00441     return;
00442 
00443   TQObject::disconnect(&d->peerResolver, 0L, this, TQT_SLOT(lookupFinishedSlot()));
00444   TQObject::disconnect(&d->localResolver, 0L, this, TQT_SLOT(lookupFinishedSlot()));
00445   if (d->peerResolver.status() < 0 || d->localResolver.status() < 0)
00446     {
00447       setState(Idle);       // backtrack
00448       setError(IO_LookupError, LookupFailure);
00449       emit stateChanged(Idle);
00450       emit gotError(LookupFailure);
00451       return;
00452     }
00453 
00454   d->localResults = d->localResolver.results();
00455   d->peerResults = d->peerResolver.results();
00456   setState(HostFound);
00457   emit stateChanged(HostFound);
00458   emit hostFound();
00459 }
00460 
00461 void KClientSocketBase::stateChanging(SocketState newState)
00462 {
00463   if (newState == Connected && socketDevice())
00464     {
00465       TQSocketNotifier *n = socketDevice()->readNotifier();
00466       if (n)
00467     {
00468       n->setEnabled(d->enableRead);
00469       TQObject::connect(n, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotReadActivity()));
00470     }
00471       else
00472     return;
00473 
00474       n = socketDevice()->writeNotifier();
00475       if (n)
00476     {
00477       n->setEnabled(d->enableWrite);
00478       TQObject::connect(n, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotWriteActivity()));
00479     }
00480       else
00481     return;
00482     }
00483 }
00484 
00485 void KClientSocketBase::copyError()
00486 {
00487   setError(socketDevice()->status(), socketDevice()->error());
00488 }
00489 
00490 #include "kclientsocketbase.moc"

tdecore

Skip menu "tdecore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

tdecore

Skip menu "tdecore"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdecore by doxygen 1.7.6.1
This website is maintained by Timothy Pearson.