• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

KDECore

kextsock.cpp

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

KDECore

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

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal