kdecore Library API Documentation

kextsock.cpp

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