| # kdecore Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

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

This file is part of the documentation for kdecore Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:18:04 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003