kdecore Library API Documentation

kextsock.cpp

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