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

tdecore

kextsock.cpp
00001 /*
00002  *  This file is part of the KDE libraries
00003  *  Copyright (C) 2000-2004 Thiago Macieira <thiago.macieira@kdemail.net>
00004  *
00005  *  This library is free software; you can redistribute it and/or
00006  *  modify it under the terms of the GNU Library General Public
00007  *  License as published by the Free Software Foundation; either
00008  *  version 2 of the License, or (at your option) any later version.
00009  *
00010  *  This library is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  *  Library General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU Library General Public License
00016  *  along with this library; see the file COPYING.LIB.  If not, write to
00017  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018  *  Boston, MA 02110-1301, USA.
00019  **/
00020 
00021 #include <config.h>
00022 
00023 #include <sys/types.h>
00024 #include <sys/socket.h>
00025 #include <sys/times.h>
00026 #include <netinet/in.h>
00027 #include <arpa/inet.h>
00028 #include <sys/un.h>
00029 
00030 #include <stdio.h>
00031 #include <errno.h>
00032 #include <fcntl.h>
00033 
00034 #include <netdb.h>
00035 
00036 #include <stdlib.h>
00037 #include <unistd.h>
00038 
00039 #include <tqglobal.h>
00040 #include <tqstring.h>
00041 #include <tqiodevice.h>
00042 #include <tqsocketnotifier.h>
00043 #include <tqguardedptr.h>
00044 
00045 #include "kresolver.h"
00046 
00047 #include "kdebug.h"
00048 #include "kextsock.h"
00049 #include "ksockaddr.h"
00050 #include "ksocks.h"
00051 
00052 #ifdef __CYGWIN__
00053 #include "netsupp.h"
00054 #endif 
00055 
00056 using namespace KNetwork;
00057 
00058 //
00059 // Internal class definitions
00060 //
00061 
00062 class KExtendedSocketPrivate
00063 {
00064 public:
00065   int flags;            // socket flags
00066   int status;           // status
00067   int syserror;         // the system error value
00068 
00069   timeval timeout;      // connection/acception timeout
00070 
00071   KResolver resRemote;      // the resolved addresses
00072   KResolver resLocal;       // binding resolution
00073   unsigned current;     // used by the asynchronous connection
00074 
00075   ::TDESocketAddress *local;    // local socket address
00076   ::TDESocketAddress *peer; // peer socket address
00077 
00078   TQSocketNotifier *qsnIn, *qsnOut;
00079   int inMaxSize, outMaxSize;
00080   bool emitRead : 1, emitWrite : 1;
00081   mutable bool addressReusable : 1, ipv6only : 1;
00082 
00083   KExtendedSocketPrivate() :
00084     flags(0), status(0), syserror(0),
00085     current(0), local(0), peer(0),
00086     qsnIn(0), qsnOut(0), inMaxSize(-1), outMaxSize(-1), emitRead(false), emitWrite(false),
00087     addressReusable(false), ipv6only(false)
00088   {
00089     timeout.tv_sec = timeout.tv_usec = 0;
00090   }
00091 };
00092 
00093 // translate KExtendedSocket flags into KResolver ones
00094 static bool process_flags(int flags, int& socktype, int& familyMask, int& outflags)
00095 {
00096   switch (flags & (KExtendedSocket::streamSocket | KExtendedSocket::datagramSocket | KExtendedSocket::rawSocket))
00097     {
00098     case 0:
00099       /* No flags given, use default */
00100 
00101     case KExtendedSocket::streamSocket:
00102       /* streaming socket requested */
00103       socktype = SOCK_STREAM;
00104       break;
00105 
00106     case KExtendedSocket::datagramSocket:
00107       /* datagram packet socket requested */
00108       socktype = SOCK_DGRAM;
00109       break;
00110 
00111     case KExtendedSocket::rawSocket:
00112       /* raw socket requested. I wouldn't do this if I were you... */
00113       socktype = SOCK_RAW;
00114       break;
00115 
00116     default:
00117       /* the flags were used in an invalid manner */
00118       return false;
00119     }
00120 
00121   if (flags & KExtendedSocket::knownSocket)
00122     {
00123       familyMask = 0;
00124       if ((flags & KExtendedSocket::unixSocket) == KExtendedSocket::unixSocket)
00125     familyMask |= KResolver::UnixFamily;
00126 
00127       switch ((flags & (KExtendedSocket::ipv6Socket|KExtendedSocket::ipv4Socket)))
00128     {
00129     case KExtendedSocket::ipv4Socket:
00130       familyMask |= KResolver::IPv4Family;
00131       break;
00132     case KExtendedSocket::ipv6Socket:
00133       familyMask |= KResolver::IPv6Family;
00134       break;
00135     case KExtendedSocket::inetSocket:
00136       familyMask |= KResolver::InternetFamily;
00137       break;
00138     }
00139 
00140       // those are all the families we know about
00141     }
00142   else
00143     familyMask = KResolver::KnownFamily;
00144 
00145   /* check other flags */
00146   outflags = (flags & KExtendedSocket::passiveSocket ? KResolver::Passive : 0) |
00147     (flags & KExtendedSocket::canonName ? KResolver::CanonName : 0) |
00148     (flags & KExtendedSocket::noResolve ? KResolver::NoResolve : 0);
00149 
00150   if (getenv("TDE_NO_IPV6"))
00151     familyMask &= ~KResolver::IPv6Family;
00152 
00153   return true;
00154 }
00155 
00156 // "skips" at most len bytes from file descriptor fd
00157 // that is, we will try and read that much data and discard
00158 // it. We will stop when we have read those or when the read
00159 // function returns error
00160 static int skipData(int fd, unsigned len)
00161 {
00162   char buf[1024];
00163   unsigned skipped = 0;
00164   while (len)
00165     {
00166       int count = sizeof(buf);
00167       if ((unsigned)count > len)
00168     count = len;
00169       count = KSocks::self()->read(fd, buf, count);
00170       if (count == -1)
00171     return -1;
00172       else
00173     {
00174       len -= count;
00175       skipped += count;
00176     }
00177     }
00178   return skipped;
00179 }
00180 
00181 /*
00182  * class KExtendedSocket
00183  */
00184 
00185 // default constructor
00186 KExtendedSocket::KExtendedSocket() :
00187   sockfd(-1), d(new KExtendedSocketPrivate)
00188 {
00189 }
00190 
00191 // constructor with hostname
00192 KExtendedSocket::KExtendedSocket(const TQString& host, int port, int flags) :
00193   sockfd(-1), d(new KExtendedSocketPrivate)
00194 {
00195   setAddress(host, port);
00196   setSocketFlags(flags);
00197 }
00198 
00199 // same
00200 KExtendedSocket::KExtendedSocket(const TQString& host, const TQString& service, int flags) :
00201   sockfd(-1), d(new KExtendedSocketPrivate)
00202 {
00203   setAddress(host, service);
00204   setSocketFlags(flags);
00205 }
00206 
00207 // destroy the class
00208 KExtendedSocket::~KExtendedSocket()
00209 {
00210   closeNow();
00211 
00212   if (d->local != NULL)
00213     delete d->local;
00214   if (d->peer != NULL)
00215     delete d->peer;
00216 
00217   if (d->qsnIn != NULL)
00218     delete d->qsnIn;
00219   if (d->qsnOut != NULL)
00220     delete d->qsnOut;
00221 
00222   delete d;
00223 }
00224 
00225 #ifdef USE_QT3
00226 void KExtendedSocket::reset()
00227 #endif // USE_QT3
00228 #ifdef USE_QT4
00229 bool KExtendedSocket::reset()
00230 #endif // USE_QT4
00231 {
00232   closeNow();
00233   release();
00234   d->current = 0;
00235   d->status = nothing;
00236   d->syserror = 0;
00237 }
00238 
00239 int KExtendedSocket::socketStatus() const
00240 {
00241   return d->status;
00242 }
00243 
00244 void KExtendedSocket::setSocketStatus(int newstatus)
00245 {
00246   d->status = newstatus;
00247 }
00248 
00249 void KExtendedSocket::setError(int errorcode, int syserror)
00250 {
00251   setStatus(errorcode);
00252   d->syserror = syserror;
00253 }
00254 
00255 int KExtendedSocket::systemError() const
00256 {
00257   return d->syserror;
00258 }
00259 
00260 /*
00261  * Sets socket flags
00262  * This is only allowed if we are in nothing state
00263  */
00264 int KExtendedSocket::setSocketFlags(int flags)
00265 {
00266   if (d->status > nothing)
00267     return -1;          // error!
00268 
00269   return d->flags = flags;
00270 }
00271 
00272 int KExtendedSocket::socketFlags() const
00273 {
00274   return d->flags;
00275 }
00276 
00277 /*
00278  * Sets socket target hostname
00279  * This is only allowed if we are in nothing state
00280  */
00281 bool KExtendedSocket::setHost(const TQString& host)
00282 {
00283   if (d->status > nothing)
00284     return false;       // error!
00285 
00286   d->resRemote.setNodeName(host);
00287   return true;
00288 }
00289 
00290 /*
00291  * returns the hostname
00292  */
00293 TQString KExtendedSocket::host() const
00294 {
00295   return d->resRemote.nodeName();
00296 }
00297 
00298 /*
00299  * Sets the socket target port/service
00300  * Same thing: only state 'nothing'
00301  */
00302 bool KExtendedSocket::setPort(int port)
00303 {
00304   return setPort(TQString::number(port));
00305 }
00306 
00307 bool KExtendedSocket::setPort(const TQString& service)
00308 {
00309   if (d->status > nothing)
00310     return false;       // error
00311 
00312   d->resRemote.setServiceName(service);
00313   return true;
00314 }
00315 
00316 /*
00317  * returns the service port number
00318  */
00319 TQString KExtendedSocket::port() const
00320 {
00321   return d->resRemote.serviceName();
00322 }
00323 
00324 /*
00325  * sets the address
00326  */
00327 bool KExtendedSocket::setAddress(const TQString& host, int port)
00328 {
00329   return setHost(host) && setPort(port);
00330 }
00331 
00332 /*
00333  * the same
00334  */
00335 bool KExtendedSocket::setAddress(const TQString& host, const TQString& serv)
00336 {
00337   return setHost(host) && setPort(serv);
00338 }
00339 
00340 /*
00341  * Sets the bind hostname
00342  * This is only valid in the 'nothing' state and if this is not a
00343  * passiveSocket socket
00344  */
00345 bool KExtendedSocket::setBindHost(const TQString& host)
00346 {
00347   if (d->status > nothing || d->flags & passiveSocket)
00348     return false;       // error
00349 
00350   d->resLocal.setServiceName(host);
00351   return true;
00352 }
00353 
00354 /*
00355  * Unsets the bind hostname
00356  * same thing
00357  */
00358 bool KExtendedSocket::unsetBindHost()
00359 {
00360   return setBindHost(TQString::null);
00361 }
00362 
00363 /*
00364  * returns the binding host
00365  */
00366 TQString KExtendedSocket::bindHost() const
00367 {
00368   return d->resLocal.serviceName();
00369 }
00370 
00371 /*
00372  * Sets the bind port
00373  * Same condition as setBindHost
00374  */
00375 bool KExtendedSocket::setBindPort(int port)
00376 {
00377   return setBindPort(TQString::number(port));
00378 }
00379 
00380 bool KExtendedSocket::setBindPort(const TQString& service)
00381 {
00382   if (d->status > nothing || d->flags & passiveSocket)
00383     return false;       // error
00384 
00385   d->resLocal.setServiceName(service);
00386   return true;
00387 }
00388 
00389 /*
00390  * unsets the bind port
00391  */
00392 bool KExtendedSocket::unsetBindPort()
00393 {
00394   return setBindPort(TQString::null);
00395 }
00396 
00397 /*
00398  * returns the binding port
00399  */
00400 TQString KExtendedSocket::bindPort() const
00401 {
00402   return d->resLocal.serviceName();
00403 }
00404 
00405 /*
00406  * sets the binding address
00407  */
00408 bool KExtendedSocket::setBindAddress(const TQString& host, int port)
00409 {
00410   return setBindHost(host) && setBindPort(port);
00411 }
00412 
00413 /*
00414  * same
00415  */
00416 bool KExtendedSocket::setBindAddress(const TQString& host, const TQString& service)
00417 {
00418   return setBindHost(host) && setBindPort(service);
00419 }
00420 
00421 /*
00422  * unsets binding address
00423  */
00424 bool KExtendedSocket::unsetBindAddress()
00425 {
00426   return unsetBindHost() && unsetBindPort();
00427 }
00428 
00429 /*
00430  * sets the timeout for the connection
00431  */
00432 bool KExtendedSocket::setTimeout(int secs, int usecs)
00433 {
00434   if (d->status >= connected)   // closed?
00435     return false;
00436 
00437   d->timeout.tv_sec = secs;
00438   d->timeout.tv_usec = usecs;
00439   return true;
00440 }
00441 
00442 /*
00443  * returns the timeout
00444  */
00445 timeval KExtendedSocket::timeout() const
00446 {
00447   return d->timeout;
00448 }
00449 
00450 /*
00451  * Sets the blocking mode on this socket
00452  */
00453 bool KExtendedSocket::setBlockingMode(bool enable)
00454 {
00455   cleanError();
00456   if (d->status < created)
00457     return false;
00458 
00459   if (sockfd == -1)
00460     return false;       // error!
00461 
00462   int fdflags = fcntl(sockfd, F_GETFL, 0);
00463   if (fdflags == -1)
00464     return false;       // error!
00465 
00466   if (!enable)
00467     fdflags |= O_NONBLOCK;
00468   else
00469     fdflags &= ~O_NONBLOCK;
00470 
00471   if (fcntl(sockfd, F_SETFL, fdflags) == -1)
00472     {
00473       setError(IO_UnspecifiedError, errno);
00474       return false;
00475     }
00476   return true;
00477 }
00478 
00479 /*
00480  * Returns the blocking mode on the socket
00481  */
00482 bool KExtendedSocket::blockingMode()
00483 {
00484   cleanError();
00485   if (d->status < created)
00486     return false;       // sockets not created are in blocking mode
00487 
00488   if (sockfd == -1)
00489     return false;       // error
00490 
00491   int fdflags = fcntl(sockfd, F_GETFL, 0);
00492   if (fdflags == -1)
00493     {
00494       setError(IO_UnspecifiedError, errno);
00495       return false;
00496     }
00497   return (fdflags & O_NONBLOCK) == 0; // non-blocking == false
00498 }
00499 
00500 /*
00501  * Sets the reusability flag for this socket in the OS
00502  */
00503 bool KExtendedSocket::setAddressReusable(bool enable)
00504 {
00505   cleanError();
00506   d->addressReusable = enable;
00507   if (d->status < created)
00508     return true;
00509 
00510   if (sockfd == -1)
00511     return true;
00512 
00513   if (!setAddressReusable(sockfd, enable))
00514     {
00515       setError(IO_UnspecifiedError, errno);
00516       return false;
00517     }
00518   return true;
00519 }
00520 
00521 bool KExtendedSocket::setAddressReusable(int fd, bool enable)
00522 {
00523   if (fd == -1)
00524     return false;
00525 
00526   int on = enable;      // just to be on the safe side
00527 
00528   if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof(on)) == -1)
00529     return false;
00530   return true;
00531 }
00532 
00533 /*
00534  * Retrieves the reusability flag for this socket
00535  */
00536 bool KExtendedSocket::addressReusable()
00537 {
00538   cleanError();
00539   if (d->status < created)
00540     return d->addressReusable;
00541 
00542   if (sockfd == -1)
00543     return d->addressReusable;
00544 
00545   int on;
00546   socklen_t onsiz = sizeof(on);
00547   if (getsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char*)&on, &onsiz) == -1)
00548     {
00549       setError(IO_UnspecifiedError, errno);
00550       return false;
00551     }
00552 
00553   return on != 0;
00554 }
00555 
00556 /*
00557  * Set the IPV6_V6ONLY flag
00558  */
00559 bool KExtendedSocket::setIPv6Only(bool enable)
00560 {
00561 #ifdef IPV6_V6ONLY
00562   cleanError();
00563 
00564   d->ipv6only = enable;
00565   if (sockfd == -1)
00566     return true;        // can't set on a non-existing socket
00567 
00568   int on = enable;
00569 
00570   if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY,
00571          (char *)&on, sizeof(on)) == -1)
00572     {
00573       setError(IO_UnspecifiedError, errno);
00574       return false;
00575     }
00576   else
00577     return true;
00578 
00579 #else
00580   // we don't have the IPV6_V6ONLY constant in this system
00581   d->ipv6only = enable;
00582 
00583   setError(IO_UnspecifiedError, ENOSYS);
00584   return false;         // can't set if we don't know about this flag
00585 #endif
00586 }
00587 
00588 /*
00589  * retrieve the IPV6_V6ONLY flag
00590  */
00591 bool KExtendedSocket::isIPv6Only()
00592 {
00593 #ifdef IPV6_V6ONLY
00594   cleanError();
00595 
00596   if (d->status < created || sockfd == -1)
00597     return d->ipv6only;
00598 
00599   int on;
00600   socklen_t onsiz = sizeof(on);
00601   if (getsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY,
00602          (char *)&on, &onsiz) == -1)
00603     {
00604       setError(IO_UnspecifiedError, errno);
00605       return false;
00606     }
00607 
00608   return d->ipv6only = on;
00609 
00610 #else
00611   // we don't have the constant
00612   setError(IO_UnspecifiedError, ENOSYS);
00613   return false;
00614 #endif
00615 }
00616 
00617 /*
00618  * Sets the buffer sizes in this socket
00619  * Also, we create or delete the socket notifiers
00620  */
00621 bool KExtendedSocket::setBufferSize(int rsize, int wsize)
00622 {
00623   cleanError();
00624   if (d->status < created)
00625     return false;
00626 
00627   if (sockfd == -1)
00628     return false;
00629 
00630   if (d->flags & passiveSocket)
00631     return false;       // no I/O on passive sockets
00632 
00633   if (rsize < -2)
00634     return false;
00635 
00636   if (wsize < -2)
00637     return false;
00638 
00639   // LOCK BUFFER MUTEX
00640 
00641   // The input socket notifier is always enabled
00642   // That happens because we want to be notified of when the socket gets
00643   // closed
00644   if (d->qsnIn == NULL)
00645     {
00646       d->qsnIn = new TQSocketNotifier(sockfd, TQSocketNotifier::Read);
00647       TQObject::connect(d->qsnIn, TQT_SIGNAL(activated(int)), this, TQT_SLOT(socketActivityRead()));
00648       d->qsnIn->setEnabled(true);
00649     }
00650 
00651   if (rsize == 0 && d->flags & inputBufferedSocket)
00652     {
00653       // user wants to disable input buffering
00654       d->flags &= ~inputBufferedSocket;
00655 
00656       consumeReadBuffer(readBufferSize(), NULL, true);
00657       d->inMaxSize = 0;
00658     }
00659   else if (rsize != -2)
00660     {
00661       // enabling input buffering
00662       if (rsize)
00663     d->flags |= inputBufferedSocket;
00664       d->inMaxSize = rsize;
00665 
00666       if (rsize > 0 && (unsigned)rsize < readBufferSize())
00667     // input buffer has more data than the new size; discard
00668     consumeReadBuffer(readBufferSize() - rsize, NULL, true);
00669 
00670     }
00671 
00672   if (wsize == 0 && d->flags & outputBufferedSocket)
00673     {
00674       // disabling output buffering
00675       d->flags &= ~outputBufferedSocket;
00676       if (d->qsnOut && !d->emitWrite)
00677     d->qsnOut->setEnabled(false);
00678       consumeWriteBuffer(writeBufferSize());
00679       d->outMaxSize = 0;
00680     }
00681   else if (wsize != -2)
00682     {
00683       // enabling input buffering
00684       if (wsize)
00685     d->flags |= outputBufferedSocket;
00686       d->outMaxSize = wsize;
00687 
00688       if (wsize > 0 && (unsigned)wsize < writeBufferSize())
00689     // output buffer is bigger than it is to become; shrink
00690     consumeWriteBuffer(writeBufferSize() - wsize);
00691 
00692       if (d->qsnOut == NULL)
00693     {
00694       d->qsnOut = new TQSocketNotifier(sockfd, TQSocketNotifier::Write);
00695       TQObject::connect(d->qsnOut, TQT_SIGNAL(activated(int)), this, TQT_SLOT(socketActivityWrite()));
00696       // if the class is being created now, there's nothing to write yet
00697       // so socketActivityWrite() will get called once and disable
00698       // the notifier
00699     }
00700     }
00701 
00702   // UNLOCK BUFFER MUTEX
00703 
00704   setFlags((mode() & ~IO_Raw) | ((d->flags & bufferedSocket) ? 0 : IO_Raw));
00705 
00706   // check we didn't turn something off we shouldn't
00707   if (d->emitWrite && d->qsnOut == NULL)
00708     {
00709       d->qsnOut = new TQSocketNotifier(sockfd, TQSocketNotifier::Write);
00710       TQObject::connect(d->qsnOut, TQT_SIGNAL(activated(int)), this, TQT_SLOT(socketActivityWrite()));
00711     }
00712 
00713   return true;
00714 }
00715 
00716 /*
00717  * Finds the local address for this socket
00718  * if we have done this already, we return it. Otherwise, we'll have
00719  * to find the socket name
00720  */
00721 const ::TDESocketAddress *KExtendedSocket::localAddress()
00722 {
00723   if (d->local != NULL)
00724     return d->local;
00725   if (d->status < bound)
00726     return NULL;
00727 
00728   return d->local = localAddress(sockfd);
00729 }
00730 
00731 /*
00732  * Same thing, but for peer address. Which means this does not work on
00733  * passiveSocket and that we require to be connected already. Also note that
00734  * the behavior on connectionless sockets is not defined here.
00735  */
00736 const ::TDESocketAddress* KExtendedSocket::peerAddress()
00737 {
00738   if (d->peer != NULL)
00739     return d->peer;
00740   if (d->flags & passiveSocket || d->status < connected)
00741     return NULL;
00742 
00743   return d->peer = peerAddress(sockfd);
00744 }
00745 
00746 /*
00747  * Perform the lookup on the addresses given
00748  */
00749 int KExtendedSocket::lookup()
00750 {
00751   if (startAsyncLookup() != 0)
00752     return -1;
00753 
00754   if (!d->resRemote.wait() || !d->resLocal.wait())
00755     {
00756       d->status = nothing;
00757       return -1;
00758     }
00759 
00760   d->status = lookupDone;
00761   if (d->resRemote.error() != KResolver::NoError)
00762     return d->resRemote.error();
00763   if (d->resLocal.error() != KResolver::NoError)
00764     return d->resLocal.error();
00765   return 0;
00766 }
00767 
00768 /*
00769  * Performs an asynchronous lookup on the given address(es)
00770  */
00771 int KExtendedSocket::startAsyncLookup()
00772 {
00773   cleanError();
00774   if (d->status > lookupInProgress)
00775     return -1;
00776   if (d->status == lookupInProgress)
00777     // already in progress
00778     return 0;
00779 
00780   /* check socket type flags */
00781   int socktype, familyMask, flags;
00782   if (!process_flags(d->flags, socktype, familyMask, flags))
00783     return -2;
00784 
00785   // perform the global lookup before
00786   if (!d->resRemote.isRunning())
00787     {
00788       d->resRemote.setFlags(flags);
00789       d->resRemote.setFamily(familyMask);
00790       d->resRemote.setSocketType(socktype);
00791       TQObject::connect(&d->resRemote, TQT_SIGNAL(finished(KResolverResults)), 
00792                this, TQT_SLOT(dnsResultsReady()));
00793 
00794       if (!d->resRemote.start())
00795     {
00796       setError(IO_LookupError, d->resRemote.error());
00797       return d->resRemote.error();
00798     }
00799     }
00800 
00801   if ((d->flags & passiveSocket) == 0 && !d->resLocal.isRunning())
00802     {
00803       /* keep flags, but make this passive */
00804       flags |= KResolver::Passive;
00805       d->resLocal.setFlags(flags);
00806       d->resLocal.setFamily(familyMask);
00807       d->resLocal.setSocketType(socktype);
00808       TQObject::connect(&d->resLocal, TQT_SIGNAL(finished(KResolverResults)), 
00809                this, TQT_SLOT(dnsResultsReady()));
00810 
00811       if (!d->resLocal.start())
00812     {
00813       setError(IO_LookupError, d->resLocal.error());
00814       return d->resLocal.error();
00815     }
00816     }
00817 
00818   // if we are here, there were no errors
00819   if (d->resRemote.isRunning() || d->resLocal.isRunning())
00820     d->status = lookupInProgress; // only if there actually is a running lookup
00821   else
00822     {
00823       d->status = lookupDone;
00824       emit lookupFinished(d->resRemote.results().count() + 
00825               d->resLocal.results().count());
00826     }
00827   return 0;
00828 }
00829 
00830 void KExtendedSocket::cancelAsyncLookup()
00831 {
00832   cleanError();
00833   if (d->status != lookupInProgress)
00834     return;         // what's to cancel?
00835 
00836   d->status = nothing;
00837   d->resLocal.cancel(false);
00838   d->resRemote.cancel(false);
00839 }
00840 
00841 int KExtendedSocket::listen(int N)
00842 {
00843   cleanError();
00844   if ((d->flags & passiveSocket) == 0 || d->status >= listening)
00845     return -2;
00846   if (d->status < lookupDone)
00847     if (lookup() != 0)
00848       return -2;        // error!
00849   if (d->resRemote.error())
00850     return -2;
00851   
00852   // doing the loop:
00853   KResolverResults::const_iterator it;
00854   KResolverResults res = d->resRemote.results();
00855   for (it = res.begin(); it != res.end(); ++it)
00856     {
00857       //kdDebug(170) << "Trying to listen on " << (*it).address().toString() << endl;
00858       sockfd = ::socket((*it).family(), (*it).socketType(), (*it).protocol());
00859       if (sockfd == -1)
00860     {
00861       // socket failed creating
00862       //kdDebug(170) << "Failed to create: " << perror << endl;
00863       continue;
00864     }
00865     
00866       fcntl(sockfd, F_SETFD, FD_CLOEXEC);
00867 
00868       if (d->addressReusable)
00869     setAddressReusable(sockfd, true);
00870       setIPv6Only(d->ipv6only);
00871       cleanError();
00872       if (KSocks::self()->bind(sockfd, (*it).address().address(), (*it).length()) == -1)
00873     {
00874       //kdDebug(170) << "Failed to bind: " << perror << endl;
00875       ::close(sockfd);
00876       sockfd = -1;
00877       continue;
00878     }
00879 
00880       // ok, socket has bound
00881       // kdDebug(170) << "Socket bound: " << sockfd << endl;
00882 
00883       d->status = bound;
00884       break;
00885     }
00886 
00887   if (sockfd == -1)
00888     {
00889       setError(IO_ListenError, errno);
00890       //kdDebug(170) << "Listen error - sockfd is -1 " << endl;
00891       return -1;
00892     }
00893 
00894   d->status = bound;
00895   setFlags(IO_Sequential | IO_Raw | IO_ReadWrite);
00896 
00897   int retval = KSocks::self()->listen(sockfd, N);
00898   if (retval == -1)
00899     setError(IO_ListenError, errno);
00900   else
00901     {
00902       d->status = listening;
00903       d->qsnIn = new TQSocketNotifier(sockfd, TQSocketNotifier::Read);
00904       TQObject::connect(d->qsnIn, TQT_SIGNAL(activated(int)), this, TQT_SLOT(socketActivityRead()));
00905     }
00906   return retval == -1 ? -1 : 0;
00907 }
00908 
00909 int KExtendedSocket::accept(KExtendedSocket *&sock)
00910 {
00911   cleanError();
00912   sock = NULL;
00913   if ((d->flags & passiveSocket) == 0 || d->status >= accepting)
00914     return -2;
00915   if (d->status < listening)
00916     if (listen() < 0)
00917       return -2;        // error!
00918 
00919   // let's see
00920   // if we have a timeout in place, we have to place this socket in non-blocking
00921   // mode
00922   bool block = blockingMode();
00923   struct sockaddr sa;
00924   ksocklen_t len = sizeof(sa);
00925   sock = NULL;
00926 
00927   if (d->timeout.tv_sec > 0 || d->timeout.tv_usec > 0)
00928     {
00929       fd_set set;
00930 
00931       setBlockingMode(false);   // turn on non-blocking
00932       FD_ZERO(&set);
00933       FD_SET(sockfd, &set);
00934 
00935       //kdDebug(170).form("Accepting on %d with %d.%06d second timeout\n",
00936       //         sockfd, d->timeout.tv_sec, d->timeout.tv_usec);
00937       // check if there is anything to accept now
00938       int retval = KSocks::self()->select(sockfd + 1, &set, NULL, NULL, &d->timeout);
00939       if (retval == -1)
00940     {
00941       setError(IO_UnspecifiedError, errno);
00942       return -1;        // system error
00943     }
00944       else if (retval == 0 || !FD_ISSET(sockfd, &set))
00945     {
00946       setError(IO_TimeOutError, 0);
00947       return -3;        // timeout
00948     }
00949     }
00950 
00951   // it's common stuff here
00952   int newfd = KSocks::self()->accept(sockfd, &sa, &len);
00953 
00954   if (newfd == -1)
00955     {
00956       setError(IO_AcceptError, errno);
00957       kdWarning(170) << "Error accepting on socket " << sockfd << ":"
00958              << perror << endl;
00959       return -1;
00960     }
00961 
00962   fcntl(newfd, F_SETFD, FD_CLOEXEC);
00963 
00964   //kdDebug(170).form("Socket %d accepted socket %d\n", sockfd, newfd);
00965 
00966   setBlockingMode(block);   // restore blocking mode
00967 
00968   sock = new KExtendedSocket;
00969   sock->d->status = connected;
00970   sock->sockfd = newfd;
00971   sock->setFlags(IO_Sequential | IO_Raw | IO_ReadWrite | IO_Open | IO_Async);
00972   sock->setBufferSize(0, 0);    // always unbuffered here. User can change that later
00973 
00974   return 0;
00975 }
00976 
00977 /*
00978  * tries to connect
00979  *
00980  * FIXME!
00981  * This function is critical path. It has to be cleaned up and made faster
00982  */
00983 int KExtendedSocket::connect()
00984 {
00985   cleanError();
00986   if (d->flags & passiveSocket || d->status >= connected)
00987     return -2;
00988   if (d->status < lookupDone)
00989     if (lookup() != 0)
00990       return -2;
00991 
00992   timeval end, now;
00993   timeval timeout_copy = d->timeout;
00994   // Ok, things are a little tricky here
00995   // Let me explain
00996   // getaddrinfo() will return several different families of sockets
00997   // When we have to bind before we connect, we have to make sure we're binding
00998   // and connecting to the same family, or things won't work
00999 
01000   KResolverResults remote = d->resRemote.results(),
01001     local = d->resLocal.results();
01002   KResolverResults::const_iterator it, it2;
01003   //kdDebug(170) << "Starting connect to " << host() << '|' << port() 
01004   //             << ": have " << local.count() << " local entries and "
01005   //             << remote.count() << " remote" << endl;
01006 
01007   int ret = -1;
01008   for (it = remote.begin(), it2 = local.begin(); it != remote.end(); ++it)
01009     {
01010       bool doingtimeout = d->timeout.tv_sec > 0 || d->timeout.tv_usec > 0;
01011       if (doingtimeout)
01012         {
01013           gettimeofday(&end, NULL);
01014           end.tv_usec += d->timeout.tv_usec;
01015           end.tv_sec += d->timeout.tv_sec;
01016           if (end.tv_usec > 1000*1000)
01017             {
01018               end.tv_usec -= 1000*1000;
01019               end.tv_sec++;
01020             }
01021           //kdDebug(170).form("Connection with timeout of %d.%06d seconds (ends in %d.%06d)\n",
01022           //    d->timeout.tv_sec, d->timeout.tv_usec, end.tv_sec, end.tv_usec);
01023         }
01024 
01025       //kdDebug(170) << "Trying to connect to " << (*it).address().toString() << endl;
01026       if (it2 != local.end())
01027     {
01028 //    //kdDebug(170) << "Searching bind socket for family " << p->ai_family << endl;
01029       if ((*it).family() != (*it2).family())
01030         // differing families, scan local for a matching family
01031         for (it2 = local.begin(); it2 != local.end(); ++it2)
01032           if ((*it).family() == (*it2).family())
01033         break;
01034 
01035       if ((*it).family() != (*it2).family())
01036         {
01037           // no matching families for this
01038           //kdDebug(170) << "No matching family for bind socket\n";
01039           it2 = local.begin();
01040           continue;
01041         }
01042 
01043       //kdDebug(170) << "Binding on " << (*it2).address().toString() << " before connect" << endl;
01044       errno = 0;
01045       sockfd = ::socket((*it).family(), (*it).socketType(), (*it).protocol());
01046       setError(IO_ConnectError, errno);
01047       if (sockfd == -1)
01048         continue;       // cannot create this socket
01049           fcntl(sockfd, F_SETFD, FD_CLOEXEC);
01050       if (d->addressReusable)
01051         setAddressReusable(sockfd, true);
01052       setIPv6Only(d->ipv6only);
01053       cleanError();
01054       if (KSocks::self()->bind(sockfd, (*it2).address(), (*it2).length()))
01055         {
01056           //kdDebug(170) << "Bind failed: " << perror << endl;
01057           ::close(sockfd);
01058           sockfd = -1;
01059           continue;
01060         }
01061     }
01062       else
01063     {
01064       // no need to bind, just create
01065       sockfd = ::socket((*it).family(), (*it).socketType(), (*it).protocol());
01066       if (sockfd == -1)
01067         {
01068           setError(IO_ConnectError, errno);
01069           continue;
01070         }
01071           fcntl(sockfd, F_SETFD, FD_CLOEXEC);
01072       if (d->addressReusable)
01073         setAddressReusable(sockfd, true);
01074       setIPv6Only(d->ipv6only);
01075       cleanError();
01076     }
01077 
01078 //      kdDebug(170) << "Socket " << sockfd << " created" << endl;
01079       d->status = created;
01080 
01081       // check if we have to do timeout
01082       if (doingtimeout && KSocks::self()->hasWorkingAsyncConnect())
01083     {
01084       fd_set rd, wr;
01085 
01086       setBlockingMode(false);
01087 
01088       // now try and connect
01089       if (KSocks::self()->connect(sockfd, (*it).address(), (*it).length()) == -1)
01090         {
01091           // this could be EWOULDBLOCK
01092           if (errno != EWOULDBLOCK && errno != EINPROGRESS)
01093         {
01094           //kdDebug(170) << "Socket " << sockfd << " did not connect: " << perror << endl;
01095           setError(IO_ConnectError, errno);
01096           ::close(sockfd);
01097           sockfd = -1;
01098           continue; // nope, another error
01099         }
01100 
01101           FD_ZERO(&rd);
01102           FD_ZERO(&wr);
01103           FD_SET(sockfd, &rd);
01104           FD_SET(sockfd, &wr);
01105 
01106           int retval = KSocks::self()->select(sockfd + 1, &rd, &wr, NULL, &d->timeout);
01107           if (retval == -1)
01108         {
01109           setError(IO_FatalError, errno);
01110           continue; // system error
01111         }
01112           else if (retval == 0)
01113         {
01114           ::close(sockfd);
01115           sockfd = -1;
01116 //        kdDebug(170) << "Time out while trying to connect to " <<
01117 //          (*it).address().toString() << endl;
01118           setError(IO_TimeOutError, 0);
01119           ret = -3; // time out
01120 
01121                   d->timeout.tv_usec += timeout_copy.tv_usec;
01122                   d->timeout.tv_sec  += timeout_copy.tv_sec;
01123                   if (d->timeout.tv_usec < 0)
01124                     {
01125                       d->timeout.tv_usec += 1000*1000;
01126                       d->timeout.tv_sec--;
01127                     }
01128 
01129           continue;
01130         }
01131 
01132           // adjust remaining time
01133           gettimeofday(&now, NULL);
01134           d->timeout.tv_sec = end.tv_sec - now.tv_sec;
01135           d->timeout.tv_usec = end.tv_usec - now.tv_usec;
01136           if (d->timeout.tv_usec < 0)
01137         {
01138           d->timeout.tv_usec += 1000*1000;
01139           d->timeout.tv_sec--;
01140         }
01141 //        kdDebug(170).form("Socket %d activity; %d.%06d seconds remaining\n",
01142 //               sockfd, d->timeout.tv_sec, d->timeout.tv_usec);
01143 
01144           // this means that an event occurred in the socket
01145           int errcode;
01146           socklen_t len = sizeof(errcode);
01147           retval = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (char*)&errcode,
01148                   &len);
01149           if (retval == -1 || errcode != 0)
01150         {
01151           // socket did not connect
01152           //kdDebug(170) << "Socket " << sockfd << " did not connect: "
01153           //        << strerror(errcode) << endl;
01154           ::close(sockfd);
01155           sockfd = -1;
01156 
01157           // this is HIGHLY UNLIKELY
01158           if (d->timeout.tv_sec == 0 && d->timeout.tv_usec == 0)
01159             {
01160               d->status = lookupDone;
01161               setError(IO_TimeOutError, 0);
01162               return -3; // time out
01163             }
01164 
01165           setError(IO_ConnectError, errcode);
01166           continue;
01167         }
01168         }
01169 
01170       // getting here means it connected
01171       // setBufferSize() takes care of creating the socket notifiers
01172       setBlockingMode(true);
01173       d->status = connected;
01174       setFlags(IO_Sequential | IO_Raw | IO_ReadWrite | IO_Open | IO_Async);
01175       setBufferSize(d->flags & inputBufferedSocket ? -1 : 0,
01176             d->flags & outputBufferedSocket ? -1 : 0);
01177       emit connectionSuccess();
01178 //    kdDebug(170) << "Socket " << sockfd << " connected\n";
01179       return 0;
01180     }
01181       else
01182     {
01183       // without timeouts
01184       if (KSocks::self()->connect(sockfd, (*it).address(), (*it).length()) == -1)
01185         {
01186           //kdDebug(170) << "Socket " << sockfd << " to " << (*it).address().toString() 
01187           //       << " did not connect: " << perror << endl;
01188           setError(IO_ConnectError, errno);
01189           ::close(sockfd);
01190           sockfd = -1;
01191           continue;
01192         }
01193 
01194       d->status = connected;
01195       setFlags(IO_Sequential | IO_Raw | IO_ReadWrite | IO_Open | IO_Async);
01196       setBufferSize(d->flags & inputBufferedSocket ? -1 : 0,
01197             d->flags & outputBufferedSocket ? -1 : 0);
01198       emit connectionSuccess();
01199 //    kdDebug(170) << "Socket " << sockfd << " connected\n";
01200       return 0;     // it connected
01201     }
01202     }
01203 
01204   // getting here means no socket connected or stuff like that
01205   emit connectionFailed(d->syserror);
01206   //kdDebug(170) << "Failed to connect\n";
01207   return ret;
01208 }
01209 
01210 int KExtendedSocket::startAsyncConnect()
01211 {
01212   cleanError();
01213   // check status
01214   if (d->status >= connected || d->flags & passiveSocket)
01215     return -2;
01216 
01217   if (d->status == connecting)
01218     // already on async connect
01219     return 0;
01220 
01221   // check if we have to do lookup
01222   // if we do, then we'll use asynchronous lookup and use
01223   // signal lookupFinished to do connection
01224   if (d->status < lookupDone)
01225     {
01226       TQObject::connect(this, TQT_SIGNAL(lookupFinished(int)), this, TQT_SLOT(startAsyncConnectSlot()));
01227       if (d->status < lookupInProgress)
01228     return startAsyncLookup();
01229       else
01230     return 0;       // we still have to wait
01231     }
01232 
01233   // here we have d->status >= lookupDone and <= connecting
01234   // we can do our connection
01235   d->status = connecting;
01236   TQGuardedPtr<TQObject> p = TQT_TQOBJECT(this);
01237   connectionEvent();
01238   if (!p) 
01239     return -1; // We have been deleted.
01240   if (d->status < connecting)
01241     return -1;
01242   return 0;
01243 }
01244 
01245 void KExtendedSocket::cancelAsyncConnect()
01246 {
01247   if (d->status != connecting)
01248     return;
01249 
01250   if (sockfd != -1)
01251     {
01252       // we have a waiting connection
01253       if (d->qsnIn)
01254     delete d->qsnIn;
01255       if (d->qsnOut)
01256     delete d->qsnOut;
01257       d->qsnIn = d->qsnOut = NULL;
01258 
01259       ::close(sockfd);
01260       sockfd = -1;
01261     }
01262   d->status = lookupDone;
01263 }
01264 
01265 bool KExtendedSocket::open(TQ_OpenMode mode)
01266 {
01267   if (mode != IO_Raw | IO_ReadWrite)
01268     return false;       // invalid open mode
01269 
01270   if (d->flags & passiveSocket)
01271     return listen() == 0;
01272   else if (d->status < connecting)
01273     return connect() == 0;
01274   else
01275     return false;
01276 }
01277 
01278 void KExtendedSocket::close()
01279 {
01280   if (sockfd == -1 || d->status >= closing)
01281     return;         // nothing to close
01282 
01283   // LOCK BUFFER MUTEX
01284   if (d->flags & outputBufferedSocket && writeBufferSize() > 0)
01285     {
01286       // write buffer not empty, go into closing state
01287       d->status = closing;
01288       if (d->qsnIn)
01289     delete d->qsnIn;
01290       d->qsnIn = NULL;
01291       // we keep the outgoing socket notifier because we want
01292       // to send data, but not receive
01293     }
01294   else
01295     {
01296       // nope, write buffer is empty
01297       // we can close now
01298       if (d->qsnIn)
01299     delete d->qsnIn;
01300       if (d->qsnOut)
01301     delete d->qsnOut;
01302       d->qsnIn = d->qsnOut = NULL;
01303 
01304       ::close(sockfd);
01305       d->status = done;
01306       emit closed(readBufferSize() != 0 ? availRead : 0);
01307     }
01308   // UNLOCK BUFFER MUTEX
01309 }
01310 
01311 
01312 void KExtendedSocket::closeNow()
01313 {
01314   if (d->status >= done)
01315     return;         // nothing to close
01316 
01317   // close the socket
01318   delete d->qsnIn;
01319   delete d->qsnOut;
01320   d->qsnIn = d->qsnOut = NULL;
01321 
01322   if (d->status > connecting && sockfd != -1)
01323     {
01324       ::close(sockfd);
01325       sockfd = -1;
01326     }
01327   else if (d->status == connecting)
01328     cancelAsyncConnect();
01329   else if (d->status == lookupInProgress)
01330     cancelAsyncLookup();
01331 
01332   d->status = done;
01333 
01334   emit closed(closedNow |
01335           (readBufferSize() != 0 ? availRead : 0) |
01336           (writeBufferSize() != 0 ? dirtyWrite : 0));
01337 }
01338 
01339 void KExtendedSocket::release()
01340 {
01341   // release our hold on the socket
01342   sockfd = -1;
01343   d->status = done;
01344 
01345   d->resRemote.cancel(false);
01346   d->resLocal.cancel(false);
01347 
01348   if (d->local != NULL)
01349     delete d->local;
01350   if (d->peer != NULL)
01351     delete d->peer;
01352 
01353   d->peer = d->local = NULL;
01354 
01355   if (d->qsnIn != NULL)
01356     delete d->qsnIn;
01357   if (d->qsnOut != NULL)
01358     delete d->qsnOut;
01359 
01360   d->qsnIn = d->qsnOut = NULL;
01361 
01362   // now that the socket notificators are done with, we can flush out the buffers
01363   consumeReadBuffer(readBufferSize(), NULL, true);
01364   consumeWriteBuffer(writeBufferSize());
01365 
01366   // don't delete d
01367   // leave that for the destructor
01368 }
01369 
01370 void KExtendedSocket::flush()
01371 {
01372   cleanError();
01373   if (d->status < connected || d->status >= done || d->flags & passiveSocket)
01374     return;
01375 
01376   if (sockfd == -1)
01377     return;
01378 
01379   if ((d->flags & outputBufferedSocket) == 0)
01380     return;         // nothing to do
01381 
01382   // LOCK MUTEX
01383 
01384   unsigned written = 0;
01385   unsigned offset = outBufIndex; // this happens only for the first
01386   while (writeBufferSize() - written > 0)
01387     {
01388       // we have to write each output buffer in outBuf
01389       // but since we can have several very small buffers, we can make things
01390       // better by concatenating a few of them into a big buffer
01391       // question is: how big should that buffer be? 16 kB should be enough
01392 
01393       TQByteArray buf(16384);
01394       TQByteArray *a = outBuf.first();
01395       unsigned count = 0;
01396 
01397       while (a && count + (a->size() - offset) <= buf.size())
01398     {
01399       memcpy(buf.data() + count, a->data() + offset, a->size() - offset);
01400       count += a->size() - offset;
01401       offset = 0;
01402       a = outBuf.next();
01403     }
01404 
01405       // see if we can still fit more
01406       if (a && count < buf.size())
01407     {
01408       // getting here means this buffer (a) is larger than
01409       // (buf.size() - count) (even for count == 0).
01410       memcpy(buf.data() + count, a->data() + offset, buf.size() - count);
01411       offset += buf.size() - count;
01412       count = buf.size();
01413     }
01414 
01415       // now try to write those bytes
01416       int wrote = KSocks::self()->write(sockfd, buf, count);
01417 
01418       if (wrote == -1)
01419     {
01420       // could be EAGAIN (EWOULDBLOCK)
01421       setError(IO_WriteError, errno);
01422       break;
01423     }
01424       written += wrote;
01425 
01426       if ((unsigned)wrote != count)
01427     break;
01428     }
01429   if (written)
01430     {
01431       consumeWriteBuffer(written);
01432       emit bytesWritten(written);
01433     }
01434 
01435   // UNLOCK MUTEX
01436 }
01437 
01438 
01439 TQT_TQIO_LONG KExtendedSocket::tqreadBlock(char *data, TQT_TQIO_ULONG maxlen)
01440 {
01441   cleanError();
01442   if (d->status < connected || d->flags & passiveSocket)
01443     return -2;
01444 
01445   int retval;
01446 
01447   if ((d->flags & inputBufferedSocket) == 0)
01448     {
01449       // we aren't buffering this socket, so just pass along
01450       // the call to the real read method
01451 
01452       if (sockfd == -1)
01453     return -2;
01454       if (data)
01455     retval = KSocks::self()->read(sockfd, data, maxlen);
01456       else
01457     retval = skipData(sockfd, maxlen);
01458       if (retval == -1)
01459     setError(IO_ReadError, errno);
01460     }
01461   else
01462     {
01463       // this socket is being buffered. So read from the buffer
01464 
01465       // LOCK BUFFER MUTEX
01466 
01467       retval = consumeReadBuffer(maxlen, data);
01468       if (retval == 0)
01469     {
01470       // consumeReadBuffer returns 0 only if the buffer is
01471       // empty
01472       if (sockfd == -1)
01473         return 0;       // buffer is clear now, indicate EOF
01474       setError(IO_ReadError, EWOULDBLOCK);
01475       retval = -1;
01476     }
01477 
01478       // UNLOCK BUFFER MUTEX
01479 
01480     }
01481   return retval;
01482 }
01483 
01484 TQT_TQIO_LONG KExtendedSocket::tqwriteBlock(const char *data, TQT_TQIO_ULONG len)
01485 {
01486   cleanError();
01487   if (d->status < connected || d->status >= closing || d->flags & passiveSocket)
01488     return -2;
01489   if (sockfd == -1)
01490     return -2;
01491 
01492   if (len == 0)
01493     return 0;           // what's to write?
01494 
01495   int retval;
01496 
01497   if ((d->flags & outputBufferedSocket) == 0)
01498     {
01499       // socket not buffered. Just call write
01500       retval = KSocks::self()->write(sockfd, data, len);
01501       if (retval == -1)
01502     setError(IO_WriteError, errno);
01503       else
01504     emit bytesWritten(retval);
01505     }
01506   else
01507     {
01508       // socket is buffered. Feed the write buffer
01509 
01510       // LOCK BUFFER MUTEX
01511 
01512       unsigned wsize = writeBufferSize();
01513       if (d->outMaxSize == (int)wsize) // (int) to get rid of annoying warning
01514     {
01515       // buffer is full!
01516       setError(IO_WriteError, EWOULDBLOCK);
01517       retval = -1;
01518     }
01519       else
01520     {
01521       if (d->outMaxSize != -1 && wsize + len > (unsigned)d->outMaxSize)
01522         // we cannot write all data. Write just as much as to fill the buffer
01523         len = d->outMaxSize - wsize;
01524 
01525       // len > 0 here
01526       retval = feedWriteBuffer(len, data);
01527       if (wsize == 0 || d->emitWrite)
01528         // buffer was empty, which means that the notifier is probably disabled
01529         d->qsnOut->setEnabled(true);
01530     }
01531 
01532       // UNLOCK BUFFER MUTEX
01533     }
01534 
01535   return retval;
01536 }
01537 
01538 int KExtendedSocket::peekBlock(char *data, uint maxlen)
01539 {
01540   if (d->status < connected || d->flags & passiveSocket)
01541     return -2;
01542   if (sockfd == -1)
01543     return -2;
01544 
01545   // need to LOCK MUTEX around this call...
01546 
01547   if (d->flags & inputBufferedSocket)
01548     return consumeReadBuffer(maxlen, data, false);
01549 
01550   return 0;
01551 }
01552 
01553 int KExtendedSocket::unreadBlock(const char *, uint)
01554 {
01555   // Always return -1, indicating this is not supported
01556   setError(IO_ReadError, ENOSYS);
01557   return -1;
01558 }
01559 
01560 #ifdef USE_QT3
01561 int KExtendedSocket::bytesAvailable() const
01562 #endif // USE_QT3
01563 #ifdef USE_QT4
01564 qint64 KExtendedSocket::bytesAvailable() const
01565 #endif // USE_QT4
01566 {
01567   if (d->status < connected || d->flags & passiveSocket)
01568     return -2;
01569 
01570   // as of now, we don't do any extra processing
01571   // we only work in input-buffered sockets
01572   if (d->flags & inputBufferedSocket)
01573     return TDEBufferedIO::bytesAvailable();
01574 
01575   return 0;         // TODO: FIONREAD ioctl
01576 }
01577 
01578 int KExtendedSocket::waitForMore(int msecs)
01579 {
01580   cleanError();
01581   if (d->flags & passiveSocket || d->status < connected || d->status >= closing)
01582     return -2;
01583   if (sockfd == -1)
01584     return -2;
01585 
01586   fd_set rd;
01587   FD_ZERO(&rd);
01588   FD_SET(sockfd, &rd);
01589   timeval tv;
01590   tv.tv_sec = msecs / 1000;
01591   tv.tv_usec = (msecs % 1000) * 1000;
01592 
01593   int retval = KSocks::self()->select(sockfd + 1, &rd, NULL, NULL, &tv);
01594   if (retval == -1)
01595     {
01596       setError(IO_FatalError, errno);
01597       return -1;
01598     }
01599   else if (retval != 0)
01600     socketActivityRead();   // do read processing
01601 
01602   return bytesAvailable();
01603 }
01604 
01605 int KExtendedSocket::getch()
01606 {
01607   unsigned char c;
01608   int retval;
01609   retval = tqreadBlock((char*)&c, sizeof(c));
01610 
01611   if (retval < 0)
01612     return retval;
01613   return c;
01614 }
01615 
01616 int KExtendedSocket::putch(int ch)
01617 {
01618   unsigned char c = (char)ch;
01619   return tqwriteBlock((char*)&c, sizeof(c));
01620 }
01621 
01622 // sets the emission of the readyRead signal
01623 void KExtendedSocket::enableRead(bool enable)
01624 {
01625   // check if we can disable the socket notifier
01626   // saves us a few cycles
01627   // this is so because in buffering mode, we rely on these signals
01628   // being emitted to do our I/O. We couldn't disable them here
01629   if (!enable && (d->flags & inputBufferedSocket) == 0 && d->qsnIn)
01630     d->qsnIn->setEnabled(false);
01631   else if (enable && d->qsnIn)
01632     // we can enable it always
01633     d->qsnIn->setEnabled(true);
01634   d->emitRead = enable;
01635 }
01636 
01637 // sets the emission of the readyWrite signal
01638 void KExtendedSocket::enableWrite(bool enable)
01639 {
01640   // same thing as above
01641   if (!enable && (d->flags & outputBufferedSocket) == 0 && d->qsnOut)
01642     d->qsnOut->setEnabled(false);
01643   else if (enable && d->qsnOut)
01644     // we can enable it always
01645     d->qsnOut->setEnabled(true);
01646   d->emitWrite = enable;
01647 }
01648 
01649 // protected slot
01650 // this is connected to d->qsnIn::activated(int)
01651 void KExtendedSocket::socketActivityRead()
01652 {
01653   if (d->flags & passiveSocket)
01654     {
01655       emit readyAccept();
01656       return;
01657     }
01658   if (d->status == connecting)
01659     {
01660       connectionEvent();
01661       return;
01662     }
01663   if (d->status != connected)
01664     return;
01665 
01666   // do we need to do I/O here?
01667   if (d->flags & inputBufferedSocket)
01668     {
01669       // aye. Do read from the socket and feed our buffer
01670       TQByteArray a;
01671       char buf[1024];
01672       int len, totalread = 0;
01673 
01674       // LOCK MUTEX
01675 
01676       unsigned cursize = readBufferSize();
01677 
01678       if (d->inMaxSize == -1 || cursize < (unsigned)d->inMaxSize)
01679     {
01680       do
01681         {
01682           // check that we can read that many bytes
01683           if (d->inMaxSize != -1 && d->inMaxSize - (cursize + totalread) < sizeof(buf))
01684         // no, that would overrun the buffer
01685         // note that this will also make us exit the loop
01686         len = d->inMaxSize - (cursize + totalread);
01687           else
01688         len = sizeof(buf);
01689 
01690           len = KSocks::self()->read(sockfd, buf, len);
01691           if (len > 0)
01692         {
01693           // normal read operation
01694           a.resize(a.size() + len);
01695           memcpy(a.data() + totalread, buf, len);
01696           totalread += len; // totalread == a.size() now
01697         }
01698           else if (len == 0)
01699         {
01700           // EOF condition here
01701           ::close(sockfd);
01702           sockfd = -1;  // we're closed
01703           d->qsnIn->deleteLater();
01704           delete d->qsnOut;
01705           d->qsnIn = d->qsnOut = NULL;
01706           d->status = done;
01707           emit closed(involuntary |
01708                   (readBufferSize() ? availRead : 0) |
01709                   (writeBufferSize() ? dirtyWrite : 0));
01710           return;
01711         }
01712           else
01713         {
01714           // error!
01715           setError(IO_ReadError, errno);
01716           return;
01717         }
01718           // will loop only for normal read operations
01719         }
01720       while (len == sizeof(buf));
01721 
01722       feedReadBuffer(a.size(), a.data());
01723     }
01724 
01725       // UNLOCK MUTEX
01726     }
01727   else
01728     {
01729       // No input buffering, but the notifier fired
01730       // That means that either there is data to be read or that the 
01731       // socket closed.
01732 
01733       // try to read one byte. If we can't, then the socket got closed
01734 
01735       char c;
01736       int len = KSocks::self()->recv(sockfd, &c, sizeof(c), MSG_PEEK);
01737       if (len == 0)
01738     {
01739       // yes, it's an EOF condition
01740       d->qsnIn->setEnabled(false);
01741       ::close(sockfd);
01742       sockfd = -1;
01743       d->status = done;
01744       emit closed(involuntary);
01745       return;
01746     }
01747     }
01748 
01749   if (d->emitRead)
01750     emit readyRead();
01751 }
01752 
01753 void KExtendedSocket::socketActivityWrite()
01754 {
01755   if (d->flags & passiveSocket)
01756     return;
01757   if (d->status == connecting)
01758     {
01759       connectionEvent();
01760       return;
01761     }
01762   if (d->status != connected && d->status != closing)
01763     return;
01764 
01765   flush();
01766 
01767   bool empty = writeBufferSize() == 0;
01768 
01769   if (d->emitWrite && empty)
01770     emit readyWrite();
01771   else if (!d->emitWrite)
01772     {
01773       // check if we can disable the notifier
01774       d->qsnOut->setEnabled(!empty); // leave it enabled only if we have more data to send
01775     }
01776   if (d->status == closing && empty)
01777     {
01778       // done sending the missing data!
01779       d->status = done;
01780 
01781       delete d->qsnOut;
01782       ::close(sockfd);
01783 
01784       d->qsnOut = NULL;
01785       sockfd = -1;
01786       emit closed(delayed | (readBufferSize() ? availRead : 0));
01787     }
01788 }
01789 
01790 // this function is called whenever we have a "connection event"
01791 // that is, whenever our asynchronously connecting socket throws
01792 // an event
01793 void KExtendedSocket::connectionEvent()
01794 {
01795   if (d->status != connecting)
01796     return;         // move along. There's nothing to see here
01797 
01798   KResolverResults remote = d->resRemote.results();
01799   if (remote.count() == 0)
01800     {
01801       // We have a problem! Abort?
01802       kdError(170) << "KExtendedSocket::connectionEvent() called but no data available!\n";
01803       return;
01804     }
01805 
01806   int errcode = 0;
01807 
01808   if (sockfd != -1)
01809     {
01810       // our socket has activity
01811       // find out what it was
01812       int retval;
01813       socklen_t len = sizeof(errcode);
01814       retval = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (char*)&errcode, &len);
01815 
01816       if (retval == -1 || errcode != 0)
01817     {
01818       // socket activity and there was error?
01819       // that means the socket probably did not connect
01820       if (d->qsnIn)
01821         delete d->qsnIn;
01822       if (d->qsnOut)
01823         delete d->qsnOut;
01824       ::close(sockfd);
01825 
01826       sockfd = -1;
01827       d->qsnIn = d->qsnOut = NULL;
01828       d->current++;
01829       setError(IO_ConnectError, errcode);
01830     }
01831       else
01832     {
01833       // hmm, socket activity and there was no error?
01834       // that means it connected
01835       // YAY!
01836       cleanError();
01837       d->status = connected;
01838       setBlockingMode(true);
01839       setFlags(IO_Sequential | IO_Raw | IO_ReadWrite | IO_Open | IO_Async);
01840       setBufferSize(d->flags & inputBufferedSocket ? -1 : 0,
01841             d->flags & outputBufferedSocket ? -1 : 0);
01842       emit connectionSuccess();
01843       return;
01844     }
01845     }
01846 
01847   // ok, we have to try something here
01848   // and sockfd == -1
01849   KResolverResults local = d->resLocal.results();
01850   unsigned localidx = 0;
01851   for ( ; d->current < remote.count(); d->current++)
01852     {
01853       // same code as in connect()
01854       if (local.count() != 0)
01855     {
01856       // scan bindres for a local resuls family
01857       for (localidx = 0; localidx < local.count(); localidx++)
01858         if (remote[d->current].family() == local[localidx].family())
01859           break;
01860 
01861       if (remote[d->current].family() != local[localidx].family())
01862         {
01863           // no matching families for this
01864           continue;
01865         }
01866 
01867       errno = 0;
01868       sockfd = ::socket(remote[d->current].family(), remote[d->current].socketType(),
01869                 remote[d->current].protocol());
01870       setError(IO_ConnectError, errno);
01871       errcode = errno;
01872       if (sockfd == -1)
01873         continue;       // cannot create this socket
01874           fcntl(sockfd, F_SETFD, FD_CLOEXEC);
01875       if (d->addressReusable)
01876         setAddressReusable(sockfd, true);
01877       setIPv6Only(d->ipv6only);
01878       cleanError();
01879       if (KSocks::self()->bind(sockfd, local[localidx].address(), 
01880                    local[localidx].length()) == -1)
01881         {
01882           ::close(sockfd);
01883           sockfd = -1;
01884           continue;
01885         }
01886     }
01887       else
01888     {
01889       // no need to bind, just create
01890       sockfd = ::socket(remote[d->current].family(), remote[d->current].socketType(),
01891                 remote[d->current].protocol());
01892       if (sockfd == -1)
01893         {
01894           setError(IO_ConnectError, errno);
01895           errcode = errno;
01896           continue;
01897         }
01898           fcntl(sockfd, F_SETFD, FD_CLOEXEC);
01899       if (d->addressReusable)
01900         setAddressReusable(sockfd, true);
01901       setIPv6Only(d->ipv6only);
01902       cleanError();
01903     }
01904 
01905       if (KSocks::self()->hasWorkingAsyncConnect())
01906         setBlockingMode(false);
01907       if (KSocks::self()->connect(sockfd, remote[d->current].address(), 
01908                   remote[d->current].length()) == -1)
01909     {
01910       if (errno != EWOULDBLOCK && errno != EINPROGRESS)
01911         {
01912           setError(IO_ConnectError, errno);
01913           ::close(sockfd);
01914           sockfd = -1;
01915           errcode = errno;
01916           continue;
01917         }
01918 
01919       // error here is either EWOULDBLOCK or EINPROGRESS
01920       // so, it is a good condition
01921       d->qsnIn = new TQSocketNotifier(sockfd, TQSocketNotifier::Read);
01922       TQObject::connect(d->qsnIn, TQT_SIGNAL(activated(int)), this, TQT_SLOT(socketActivityRead()));
01923       d->qsnOut = new TQSocketNotifier(sockfd, TQSocketNotifier::Write);
01924       TQObject::connect(d->qsnOut, TQT_SIGNAL(activated(int)), this, TQT_SLOT(socketActivityWrite()));
01925 
01926       // ok, let the Qt event loop do the selecting for us
01927       return;
01928     }
01929 
01930       // eh, what?
01931       // the non-blocking socket returned valid connection?
01932       // already?
01933       // I suppose that could happen...
01934       cleanError();
01935       d->status = connected;
01936       setBlockingMode(true);
01937       setFlags(IO_Sequential | IO_Raw | IO_ReadWrite | IO_Open | IO_Async);
01938       setBufferSize(d->flags & inputBufferedSocket ? -1 : 0,
01939             d->flags & outputBufferedSocket ? -1 : 0);
01940       emit connectionSuccess();
01941       return;
01942     }
01943 
01944   // if we got here, it means that there are no more options to connect
01945   d->status = lookupDone;   // go back
01946   emit connectionFailed(errcode);
01947 }
01948 
01949 void KExtendedSocket::dnsResultsReady()
01950 {
01951   // check that this function was called in a valid state
01952   if (d->status != lookupInProgress)
01953     return;
01954 
01955   // valid state. Are results fully ready?
01956   if (d->resRemote.isRunning() || d->resLocal.isRunning())
01957     // no, still waiting for answer in one of the lookups
01958     return;
01959 
01960   // ok, we have all results
01961   // count how many results we have
01962   int n = d->resRemote.results().count() + d->resLocal.results().count();
01963 
01964   if (n)
01965     {
01966       d->status = lookupDone;
01967       cleanError();
01968     }
01969   else
01970     {
01971       d->status = nothing;
01972       setError(IO_LookupError, KResolver::NoName);
01973     }
01974 
01975   emit lookupFinished(n);
01976 
01977   return;
01978 }
01979 
01980 void KExtendedSocket::startAsyncConnectSlot()
01981 {
01982   TQObject::disconnect(this, TQT_SIGNAL(lookupFinished(int)), this, TQT_SLOT(startAsyncConnectSlot()));
01983 
01984   if (d->status == lookupDone)
01985     startAsyncConnect();
01986 }
01987 
01988 int KExtendedSocket::resolve(sockaddr *sock, ksocklen_t len, TQString &host,
01989                  TQString &port, int flags)
01990 {
01991   kdDebug(170) << "Deprecated function called:" << k_funcinfo << endl;
01992 
01993   int err;
01994   char h[NI_MAXHOST], s[NI_MAXSERV];
01995 
01996   h[0] = s[0] = '\0';
01997 
01998   err = getnameinfo(sock, len, h, sizeof(h) - 1, s, sizeof(s) - 1, flags);
01999   host = TQString::fromUtf8(h);
02000   port = TQString::fromUtf8(s);
02001 
02002   return err;
02003 }
02004 
02005 int KExtendedSocket::resolve(::TDESocketAddress *sock, TQString &host, TQString &port,
02006                  int flags)
02007 {
02008   return resolve(sock->data, sock->datasize, host, port, flags);
02009 }
02010 
02011 TQPtrList<KAddressInfo> KExtendedSocket::lookup(const TQString& host, const TQString& port,
02012                         int userflags, int *error)
02013 {
02014   kdDebug(170) << "Deprecated function called:" << k_funcinfo << endl;
02015 
02016   int socktype, familyMask, flags;
02017   unsigned i;
02018   TQPtrList<KAddressInfo> l;
02019 
02020   /* check socket type flags */
02021   if (!process_flags(userflags, socktype, familyMask, flags))
02022     return l;
02023 
02024 //  kdDebug(170) << "Performing lookup on " << host << "|" << port << endl;
02025   KResolverResults res = KResolver::resolve(host, port, flags, familyMask);
02026   if (res.error())
02027     {
02028       if (error)
02029     *error = res.error();
02030       return l;
02031     }
02032 
02033   for (i = 0; i < res.count(); i++)
02034     {
02035       KAddressInfo *ai = new KAddressInfo();
02036 
02037       // I should have known that using addrinfo was going to come
02038       // and bite me back some day...
02039       ai->ai = (addrinfo *) malloc(sizeof(addrinfo));
02040       memset(ai->ai, 0, sizeof(addrinfo));
02041 
02042       ai->ai->ai_family = res[i].family();
02043       ai->ai->ai_socktype = res[i].socketType();
02044       ai->ai->ai_protocol = res[i].protocol();
02045       TQString canon = res[i].canonicalName();
02046       if (!canon.isEmpty())
02047     {
02048       ai->ai->ai_canonname = (char *) malloc(canon.length()+1);
02049       strcpy(ai->ai->ai_canonname, canon.ascii()); // ASCII here is intentional
02050     }
02051       if ((ai->ai->ai_addrlen = res[i].length()))
02052     {
02053       ai->ai->ai_addr = (struct sockaddr *) malloc(res[i].length());
02054       memcpy(ai->ai->ai_addr, res[i].address().address(), res[i].length());
02055     }
02056       else
02057     {
02058       ai->ai->ai_addr = 0;
02059     }
02060 
02061       ai->addr = ::TDESocketAddress::newAddress(ai->ai->ai_addr, ai->ai->ai_addrlen);
02062 
02063       l.append(ai);
02064     }
02065 
02066   if ( error )
02067       *error = 0;               // all is fine!
02068 
02069   return l;
02070 }
02071 
02072 ::TDESocketAddress *KExtendedSocket::localAddress(int fd)
02073 {
02074   ::TDESocketAddress *local;
02075   struct sockaddr static_sa, *sa = &static_sa;
02076   ksocklen_t len = sizeof(static_sa);
02077 
02078   /* find out the socket length, in advance
02079    * we use a sockaddr allocated on the heap just not to pass down
02080    * a NULL pointer to the first call. Some systems are reported to
02081    * set len to 0 if we pass NULL as the sockaddr */
02082   if (KSocks::self()->getsockname(fd, sa, &len) == -1)
02083     return NULL;        // error!
02084 
02085   /* was it enough? */
02086   if (len > sizeof(static_sa)
02087 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
02088       || sa->sa_len > sizeof(static_sa)
02089 #endif
02090       )
02091     {
02092       /* nope, malloc a new socket with the proper size */
02093 
02094 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
02095       if (sa->sa_len != len)
02096         len = sa->sa_len;
02097 #endif
02098 
02099       sa = (sockaddr*)malloc(len);
02100       if (sa == NULL)
02101     return NULL;        // out of memory
02102 
02103       if (KSocks::self()->getsockname(fd, sa, &len) == -1)
02104     {
02105       free(sa);
02106       return NULL;
02107     }
02108 
02109       local = ::TDESocketAddress::newAddress(sa, len);
02110       free(sa);
02111     }
02112   else
02113     local = ::TDESocketAddress::newAddress(sa, len);
02114 
02115   return local;
02116 }
02117 
02118 /* This is exactly the same code as localAddress, except
02119  * we call getpeername here */
02120 ::TDESocketAddress *KExtendedSocket::peerAddress(int fd)
02121 {
02122   ::TDESocketAddress *peer;
02123   struct sockaddr static_sa, *sa = &static_sa;
02124   ksocklen_t len = sizeof(static_sa);
02125 
02126   /* find out the socket length, in advance
02127    * we use a sockaddr allocated on the heap just not to pass down
02128    * a NULL pointer to the first call. Some systems are reported to
02129    * set len to 0 if we pass NULL as the sockaddr */
02130   if (KSocks::self()->getpeername(fd, sa, &len) == -1)
02131     return NULL;        // error!
02132 
02133   /* was it enough? */
02134   if (len > sizeof(static_sa)
02135 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
02136       || sa->sa_len > sizeof(static_sa)
02137 #endif
02138       )
02139     {
02140       /* nope, malloc a new socket with the proper size */
02141 
02142 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
02143       if (sa->sa_len != len)
02144         len = sa->sa_len;
02145 #endif
02146 
02147       sa = (sockaddr*)malloc(len);
02148       if (sa == NULL)
02149     return NULL;        // out of memory
02150 
02151       if (KSocks::self()->getpeername(fd, sa, &len) == -1)
02152     {
02153       free(sa);
02154       return NULL;
02155     }
02156 
02157       peer = ::TDESocketAddress::newAddress(sa, len);
02158       free(sa);
02159     }
02160   else
02161     peer = ::TDESocketAddress::newAddress(sa, len);
02162 
02163   return peer;
02164 }
02165 
02166 TQString KExtendedSocket::strError(int code, int syserr)
02167 {
02168   const char * msg;
02169   if (code == IO_LookupError)
02170     msg = gai_strerror(syserr);
02171   else
02172     msg = strerror(syserr);
02173 
02174   return TQString::fromLocal8Bit(msg);
02175 }
02176 
02177 
02178 TQSocketNotifier *KExtendedSocket::readNotifier() { return d->qsnIn; }
02179 TQSocketNotifier *KExtendedSocket::writeNotifier() { return d->qsnOut; }
02180 
02181 /*
02182  * class KAddressInfo
02183  */
02184 
02185 #if 0
02186 KAddressInfo::KAddressInfo(addrinfo *p)
02187 {
02188    ai = (addrinfo *) malloc(sizeof(addrinfo));
02189    memcpy(ai, p, sizeof(addrinfo));
02190    ai->ai_next = NULL;
02191    if (p->ai_canonname)
02192    {
02193       ai->ai_canonname = (char *) malloc(strlen(p->ai_canonname)+1);
02194       strcpy(ai->ai_canonname, p->ai_canonname);
02195    }
02196    if (p->ai_addr && p->ai_addrlen)
02197    {
02198       ai->ai_addr = (struct sockaddr *) malloc(p->ai_addrlen);
02199       memcpy(ai->ai_addr, p->ai_addr, p->ai_addrlen);
02200    }
02201    else
02202    {
02203       ai->ai_addr = 0;
02204       ai->ai_addrlen = 0;
02205    }
02206 
02207    addr = ::TDESocketAddress::newAddress(ai->ai_addr, ai->ai_addrlen);
02208 }
02209 #endif
02210 KAddressInfo::~KAddressInfo()
02211 {
02212   if (ai && ai->ai_canonname)
02213     free(ai->ai_canonname);
02214 
02215   if (ai && ai->ai_addr)
02216     free(ai->ai_addr);  
02217 
02218   if (ai)
02219     free(ai);
02220   delete addr;
02221 }
02222 
02223 int KAddressInfo::flags() const
02224 {
02225   return ai->ai_flags;
02226 }
02227 
02228 int KAddressInfo::family() const
02229 {
02230   return ai->ai_family;
02231 }
02232 
02233 int KAddressInfo::socktype() const
02234 {
02235   return ai->ai_socktype;
02236 }
02237 
02238 int KAddressInfo::protocol() const
02239 {
02240   return ai->ai_protocol;
02241 }
02242 
02243 const char* KAddressInfo::canonname() const
02244 {
02245   return ai->ai_canonname;
02246 }
02247 
02248 void KExtendedSocket::virtual_hook( int id, void* data )
02249 { TDEBufferedIO::virtual_hook( id, data ); }
02250 
02251 #include "kextsock.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.