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