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