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.2 2004/03/01 13:18:40 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 <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       fcntl(sockfd, F_SETFD, FD_CLOEXEC);
01157 
01158       if (d->addressReusable)
01159     setAddressReusable(sockfd, true);
01160       setIPv6Only(d->ipv6only);
01161       cleanError();
01162       if (KSocks::self()->bind(sockfd, p->ai_addr, p->ai_addrlen) == -1)
01163     {
01164       kdDebug(170) << "Failed to bind: " << perror << endl;
01165       ::close(sockfd);
01166       sockfd = -1;
01167       continue;
01168     }
01169 
01170       // ok, socket has bound
01171       // kdDebug(170) << "Socket bound: " << sockfd << endl;
01172 
01173       d->status = bound;
01174       break;
01175     }
01176 
01177   if (sockfd == -1)
01178     {
01179       setError(IO_ListenError, errno);
01180       kdDebug(170) << "Listen error - sockfd is -1 " << endl;
01181       return -1;
01182     }
01183 
01184   d->status = bound;
01185   setFlags(IO_Sequential | IO_Raw | IO_ReadWrite);
01186 
01187   int retval = KSocks::self()->listen(sockfd, N);
01188   if (retval == -1)
01189     setError(IO_ListenError, errno);
01190   else
01191     {
01192       d->status = listening;
01193       d->qsnIn = new QSocketNotifier(sockfd, QSocketNotifier::Read);
01194       QObject::connect(d->qsnIn, SIGNAL(activated(int)), this, SLOT(socketActivityRead()));
01195     }
01196   return retval == -1 ? -1 : 0;
01197 }
01198 
01199 int KExtendedSocket::accept(KExtendedSocket *&sock)
01200 {
01201   cleanError();
01202   sock = NULL;
01203   if ((d->flags & passiveSocket) == 0 || d->status >= accepting)
01204     return -2;
01205   if (d->status < listening)
01206     if (listen() < 0)
01207       return -2;        // error!
01208 
01209   // let's see
01210   // if we have a timeout in place, we have to place this socket in non-blocking
01211   // mode
01212   bool block = blockingMode();
01213   struct sockaddr sa;
01214   ksocklen_t len = sizeof(sa);
01215   sock = NULL;
01216 
01217   if (d->timeout.tv_sec > 0 || d->timeout.tv_usec > 0)
01218     {
01219       fd_set set;
01220 
01221       setBlockingMode(false);   // turn on non-blocking
01222       FD_ZERO(&set);
01223       FD_SET(sockfd, &set);
01224 
01225       //kdDebug(170).form("Accepting on %d with %d.%06d second timeout\n",
01226       //         sockfd, d->timeout.tv_sec, d->timeout.tv_usec);
01227       // check if there is anything to accept now
01228       int retval = KSocks::self()->select(sockfd + 1, &set, NULL, NULL, &d->timeout);
01229       if (retval == -1)
01230     {
01231       setError(IO_UnspecifiedError, errno);
01232       return -1;        // system error
01233     }
01234       else if (retval == 0 || !FD_ISSET(sockfd, &set))
01235     {
01236       setError(IO_TimeOutError, 0);
01237       return -3;        // timeout
01238     }
01239     }
01240 
01241   // it's common stuff here
01242   int newfd = KSocks::self()->accept(sockfd, &sa, &len);
01243 
01244   if (newfd == -1)
01245     {
01246       setError(IO_AcceptError, errno);
01247       kdWarning(170) << "Error accepting on socket " << sockfd << ":"
01248              << perror << endl;
01249       return -1;
01250     }
01251 
01252   fcntl(newfd, F_SETFD, FD_CLOEXEC);
01253 
01254   //kdDebug(170).form("Socket %d accepted socket %d\n", sockfd, newfd);
01255 
01256   setBlockingMode(block);   // restore blocking mode
01257 
01258   sock = new KExtendedSocket;
01259   sock->d->status = connected;
01260   sock->sockfd = newfd;
01261   sock->setFlags(IO_Sequential | IO_Raw | IO_ReadWrite | IO_Open | IO_Async);
01262   sock->setBufferSize(0, 0);    // always unbuffered here. User can change that later
01263 
01264   return 0;
01265 }
01266 
01267 /*
01268  * tries to connect
01269  *
01270  * FIXME!
01271  * This function is critical path. It has to be cleaned up and made faster
01272  */
01273 int KExtendedSocket::connect()
01274 {
01275   cleanError();
01276   if (d->flags & passiveSocket || d->status >= connected)
01277     return -2;
01278   if (d->status < lookupDone)
01279     if (lookup() != 0)
01280       return -2;
01281   if (!d->resolution) return -2;
01282 
01283   addrinfo *p, *q;
01284   timeval end, now;
01285   // Ok, things are a little tricky here
01286   // Let me explain
01287   // getaddrinfo() will return several different families of sockets
01288   // When we have to bind before we connect, we have to make sure we're binding
01289   // and connecting to the same family, or things won't work
01290 
01291   bool doingtimeout = d->timeout.tv_sec > 0 || d->timeout.tv_usec > 0;
01292   if (doingtimeout)
01293     {
01294       gettimeofday(&end, NULL);
01295       end.tv_usec += d->timeout.tv_usec;
01296       end.tv_sec += d->timeout.tv_sec;
01297       if (end.tv_usec > 1000*1000)
01298     {
01299       end.tv_usec -= 1000*1000;
01300       end.tv_sec++;
01301     }
01302 //  kdDebug(170).form("Connection with timeout of %d.%06d seconds (ends in %d.%06d)\n",
01303 //           d->timeout.tv_sec, d->timeout.tv_usec, end.tv_sec, end.tv_usec);
01304     }
01305 
01306   if (d->bindres)
01307     q = d->bindres->data;
01308   else
01309     q = NULL;
01310   for (p = d->resolution->data; p; p = p->ai_next)
01311     {
01312       // check for family restriction
01313       if (!valid_family(p, d->flags))
01314     continue;
01315 
01316 //      kdDebug(170) << "Trying to connect to " << pretty_sock(p) << endl;
01317       if (q != NULL)
01318     {
01319 //    kdDebug(170) << "Searching bind socket for family " << p->ai_family << endl;
01320       if (q->ai_family != p->ai_family)
01321         // differing families, scan bindres for a matching family
01322         for (q = d->bindres->data; q; q = q->ai_next)
01323           if (q->ai_family == p->ai_family)
01324         break;
01325 
01326       if (q == NULL || q->ai_family != p->ai_family)
01327         {
01328           // no matching families for this
01329           kdDebug(170) << "No matching family for bind socket\n";
01330           q = d->bindres->data;
01331           continue;
01332         }
01333 
01334       kdDebug(170) << "Binding on " << pretty_sock(q) << " before connect" << endl;
01335       errno = 0;
01336       sockfd = ::socket(p->ai_family, p->ai_socktype, p->ai_protocol);
01337       setError(IO_ConnectError, errno);
01338       if (sockfd == -1)
01339         continue;       // cannot create this socket
01340           fcntl(sockfd, F_SETFD, FD_CLOEXEC);
01341       if (d->addressReusable)
01342         setAddressReusable(sockfd, true);
01343       setIPv6Only(d->ipv6only);
01344       cleanError();
01345       if (KSocks::self()->bind(sockfd, q->ai_addr, q->ai_addrlen) == -1)
01346         {
01347           kdDebug(170) << "Bind failed: " << perror << endl;
01348           ::close(sockfd);
01349           sockfd = -1;
01350           continue;
01351         }
01352     }
01353       else
01354     {
01355       // no need to bind, just create
01356       sockfd = ::socket(p->ai_family, p->ai_socktype, p->ai_protocol);
01357       if (sockfd == -1)
01358         {
01359           setError(IO_ConnectError, errno);
01360           continue;
01361         }
01362           fcntl(sockfd, F_SETFD, FD_CLOEXEC);
01363       if (d->addressReusable)
01364         setAddressReusable(sockfd, true);
01365       setIPv6Only(d->ipv6only);
01366       cleanError();
01367     }
01368 
01369 //      kdDebug(170) << "Socket " << sockfd << " created" << endl;
01370       d->status = created;
01371 
01372       // check if we have to do timeout
01373       if (doingtimeout && KSocks::self()->hasWorkingAsyncConnect())
01374     {
01375       fd_set rd, wr;
01376 
01377       setBlockingMode(false);
01378 
01379       // now try and connect
01380       if (KSocks::self()->connect(sockfd, p->ai_addr, p->ai_addrlen) == -1)
01381         {
01382           // this could be EWOULDBLOCK
01383           if (errno != EWOULDBLOCK && errno != EINPROGRESS)
01384         {
01385           kdDebug(170) << "Socket " << sockfd << " did not connect: " << perror << endl;
01386           setError(IO_ConnectError, errno);
01387           ::close(sockfd);
01388           sockfd = -1;
01389           continue; // nope, another error
01390         }
01391 
01392           FD_ZERO(&rd);
01393           FD_ZERO(&wr);
01394           FD_SET(sockfd, &rd);
01395           FD_SET(sockfd, &wr);
01396 
01397           int retval = KSocks::self()->select(sockfd + 1, &rd, &wr, NULL, &d->timeout);
01398           if (retval == -1)
01399         {
01400           setError(IO_FatalError, errno);
01401           continue; // system error
01402         }
01403           else if (retval == 0)
01404         {
01405           ::close(sockfd);
01406           sockfd = -1;
01407           kdDebug(170) << "Time out while trying to connect to " <<
01408             pretty_sock(p) << endl;
01409           d->status = lookupDone;
01410           setError(IO_TimeOutError, 0);
01411           return -3;    // time out
01412         }
01413 
01414           // adjust remaining time
01415           gettimeofday(&now, NULL);
01416           d->timeout.tv_sec = end.tv_sec - now.tv_sec;
01417           d->timeout.tv_usec = end.tv_usec - now.tv_usec;
01418           if (d->timeout.tv_usec < 0)
01419         {
01420           d->timeout.tv_usec += 1000*1000;
01421           d->timeout.tv_sec--;
01422         }
01423 //        kdDebug(170).form("Socket %d activity; %d.%06d seconds remaining\n",
01424 //               sockfd, d->timeout.tv_sec, d->timeout.tv_usec);
01425 
01426           // this means that an event occurred in the socket
01427           int errcode;
01428           socklen_t len = sizeof(errcode);
01429           retval = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (char*)&errcode,
01430                   &len);
01431           if (retval == -1 || errcode != 0)
01432         {
01433           // socket did not connect
01434           kdDebug(170) << "Socket " << sockfd << " did not connect: "
01435                 << strerror(errcode) << endl;
01436           ::close(sockfd);
01437           sockfd = -1;
01438 
01439           // this is HIGHLY UNLIKELY
01440           if (d->timeout.tv_sec == 0 && d->timeout.tv_usec == 0)
01441             {
01442               d->status = lookupDone;
01443               setError(IO_TimeOutError, 0);
01444               return -3; // time out
01445             }
01446 
01447           setError(IO_ConnectError, errcode);
01448           continue;
01449         }
01450         }
01451 
01452       // getting here means it connected
01453       // setBufferSize() takes care of creating the socket notifiers
01454       setBlockingMode(true);
01455       d->status = connected;
01456       setFlags(IO_Sequential | IO_Raw | IO_ReadWrite | IO_Open | IO_Async);
01457       setBufferSize(d->flags & inputBufferedSocket ? -1 : 0,
01458             d->flags & outputBufferedSocket ? -1 : 0);
01459       emit connectionSuccess();
01460 //    kdDebug(170) << "Socket " << sockfd << " connected\n";
01461       return 0;
01462     }
01463       else
01464     {
01465       // without timeouts
01466       if (KSocks::self()->connect(sockfd, p->ai_addr, p->ai_addrlen) == -1)
01467         {
01468           kdDebug(170) << "Socket " << sockfd << " did not connect: " << perror << endl;
01469           setError(IO_ConnectError, errno);
01470           ::close(sockfd);
01471           sockfd = -1;
01472           continue;
01473         }
01474 
01475       d->status = connected;
01476       setFlags(IO_Sequential | IO_Raw | IO_ReadWrite | IO_Open | IO_Async);
01477       setBufferSize(d->flags & inputBufferedSocket ? -1 : 0,
01478             d->flags & outputBufferedSocket ? -1 : 0);
01479       emit connectionSuccess();
01480 //    kdDebug(170) << "Socket " << sockfd << " connected\n";
01481       return 0;     // it connected
01482     }
01483     }
01484 
01485   // getting here means no socket connected or stuff like that
01486   emit connectionFailed(d->syserror);
01487   kdDebug(170) << "Failed to connect\n";
01488   return -1;
01489 }
01490 
01491 int KExtendedSocket::startAsyncConnect()
01492 {
01493   cleanError();
01494   // check status
01495   if (d->status >= connected || d->flags & passiveSocket)
01496     return -2;
01497 
01498   if (d->status == connecting)
01499     // already on async connect
01500     return 0;
01501 
01502   // check if we have to do lookup
01503   // if we do, then we'll use asynchronous lookup and use
01504   // signal lookupFinished to do connection
01505   if (d->status < lookupDone)
01506     {
01507       QObject::connect(this, SIGNAL(lookupFinished(int)), this, SLOT(startAsyncConnectSlot()));
01508       if (d->status < lookupInProgress)
01509     return startAsyncLookup();
01510       else
01511     return 0;       // we still have to wait
01512     }
01513 
01514   // here we have d->status >= lookupDone and <= connecting
01515   // we can do our connection
01516   d->status = connecting;
01517   QGuardedPtr<QObject> p = this;
01518   connectionEvent();
01519   if (!p) 
01520     return -1; // We have been deleted.
01521   if (d->status < connecting)
01522     return -1;
01523   return 0;
01524 }
01525 
01526 void KExtendedSocket::cancelAsyncConnect()
01527 {
01528   if (d->status != connecting)
01529     return;
01530 
01531   if (sockfd != -1)
01532     {
01533       // we have a waiting connection
01534       if (d->qsnIn)
01535     delete d->qsnIn;
01536       if (d->qsnOut)
01537     delete d->qsnOut;
01538       d->qsnIn = d->qsnOut = NULL;
01539 
01540       ::close(sockfd);
01541       sockfd = -1;
01542     }
01543   d->status = lookupDone;
01544 }
01545 
01546 bool KExtendedSocket::open(int mode)
01547 {
01548   if (mode != IO_Raw | IO_ReadWrite)
01549     return false;       // invalid open mode
01550 
01551   if (d->flags & passiveSocket)
01552     return listen() == 0;
01553   else if (d->status < connecting)
01554     return connect() == 0;
01555   else
01556     return false;
01557 }
01558 
01559 void KExtendedSocket::close()
01560 {
01561   if (sockfd == -1 || d->status >= closing)
01562     return;         // nothing to close
01563 
01564   // LOCK BUFFER MUTEX
01565   if (d->flags & outputBufferedSocket && writeBufferSize() > 0)
01566     {
01567       // write buffer not empty, go into closing state
01568       d->status = closing;
01569       if (d->qsnIn)
01570     delete d->qsnIn;
01571       d->qsnIn = NULL;
01572       // we keep the outgoing socket notifier because we want
01573       // to send data, but not receive
01574     }
01575   else
01576     {
01577       // nope, write buffer is empty
01578       // we can close now
01579       if (d->qsnIn)
01580     delete d->qsnIn;
01581       if (d->qsnOut)
01582     delete d->qsnOut;
01583       d->qsnIn = d->qsnOut = NULL;
01584 
01585       ::close(sockfd);
01586       d->status = done;
01587       emit closed(readBufferSize() != 0 ? availRead : 0);
01588     }
01589   // UNLOCK BUFFER MUTEX
01590 }
01591 
01592 
01593 void KExtendedSocket::closeNow()
01594 {
01595   if (d->status >= done)
01596     return;         // nothing to close
01597 
01598   // close the socket
01599   delete d->qsnIn;
01600   delete d->qsnOut;
01601   d->qsnIn = d->qsnOut = NULL;
01602 
01603   if (d->status > connecting && sockfd != -1)
01604     {
01605       ::close(sockfd);
01606       sockfd = -1;
01607     }
01608   else if (d->status == connecting)
01609     cancelAsyncConnect();
01610   else if (d->status == lookupInProgress)
01611     cancelAsyncLookup();
01612 
01613   d->status = done;
01614 
01615   emit closed(closedNow |
01616           (readBufferSize() != 0 ? availRead : 0) |
01617           (writeBufferSize() != 0 ? dirtyWrite : 0));
01618 }
01619 
01620 void KExtendedSocket::release()
01621 {
01622   // release our hold on the socket
01623   sockfd = -1;
01624   d->status = done;
01625 
01626   // also do some garbage collecting
01627   local_freeaddrinfo(d->resolution);
01628   local_freeaddrinfo(d->bindres);
01629 
01630   d->host = d->service = d->localhost = d->localservice = (const char *)0;
01631 
01632   if (d->local != NULL)
01633     delete d->local;
01634   if (d->peer != NULL)
01635     delete d->peer;
01636 
01637   d->peer = d->local = NULL;
01638 
01639   if (d->qsnIn != NULL)
01640     delete d->qsnIn;
01641   if (d->qsnOut != NULL)
01642     delete d->qsnOut;
01643 
01644   d->qsnIn = d->qsnOut = NULL;
01645 
01646   // now that the socket notificators are done with, we can flush out the buffers
01647   consumeReadBuffer(readBufferSize(), NULL, true);
01648   consumeWriteBuffer(writeBufferSize());
01649 
01650   // don't delete d
01651   // leave that for the destructor
01652 }
01653 
01654 void KExtendedSocket::flush()
01655 {
01656   cleanError();
01657   if (d->status < connected || d->status >= done || d->flags & passiveSocket)
01658     return;
01659 
01660   if (sockfd == -1)
01661     return;
01662 
01663   if ((d->flags & outputBufferedSocket) == 0)
01664     return;         // nothing to do
01665 
01666   // LOCK MUTEX
01667 
01668   unsigned written = 0;
01669   unsigned offset = outBufIndex; // this happens only for the first
01670   while (writeBufferSize() - written > 0)
01671     {
01672       // we have to write each output buffer in outBuf
01673       // but since we can have several very small buffers, we can make things
01674       // better by concatenating a few of them into a big buffer
01675       // question is: how big should that buffer be? 16 kB should be enough
01676 
01677       QByteArray buf(16384);
01678       QByteArray *a = outBuf.first();
01679       unsigned count = 0;
01680 
01681       while (a && count + (a->size() - offset) < buf.size())
01682     {
01683       memcpy(buf.data() + count, a->data() + offset, a->size() - offset);
01684       count += a->size() - offset;
01685       offset = 0;
01686       a = outBuf.next();
01687     }
01688 
01689       // now try to write those bytes
01690       int wrote = KSocks::self()->write(sockfd, buf, count);
01691 
01692       if (wrote == -1)
01693     {
01694       // could be EAGAIN (EWOULDBLOCK)
01695       setError(IO_WriteError, errno);
01696       break;
01697     }
01698       written += wrote;
01699 
01700       if ((unsigned)wrote != count)
01701     break;
01702     }
01703   if (written)
01704     {
01705       consumeWriteBuffer(written);
01706       emit bytesWritten(written);
01707     }
01708 
01709   // UNLOCK MUTEX
01710 }
01711 
01712 
01713 Q_LONG KExtendedSocket::readBlock(char *data, Q_ULONG maxlen)
01714 {
01715   cleanError();
01716   if (d->status < connected || d->flags & passiveSocket)
01717     return -2;
01718 
01719   int retval;
01720 
01721   if ((d->flags & inputBufferedSocket) == 0)
01722     {
01723       // we aren't buffering this socket, so just pass along
01724       // the call to the real read method
01725 
01726       if (sockfd == -1)
01727     return -2;
01728       if (data)
01729     retval = KSocks::self()->read(sockfd, data, maxlen);
01730       else
01731     retval = skipData(sockfd, maxlen);
01732       if (retval == -1)
01733     setError(IO_ReadError, errno);
01734     }
01735   else
01736     {
01737       // this socket is being buffered. So read from the buffer
01738 
01739       // LOCK BUFFER MUTEX
01740 
01741       retval = consumeReadBuffer(maxlen, data);
01742       if (retval == 0)
01743     {
01744       // consumeReadBuffer returns 0 only if the buffer is
01745       // empty
01746       if (sockfd == -1)
01747         return 0;       // buffer is clear now, indicate EOF
01748       setError(IO_ReadError, EWOULDBLOCK);
01749       retval = -1;
01750     }
01751 
01752       // UNLOCK BUFFER MUTEX
01753 
01754     }
01755   return retval;
01756 }
01757 
01758 Q_LONG KExtendedSocket::writeBlock(const char *data, Q_ULONG len)
01759 {
01760   cleanError();
01761   if (d->status < connected || d->status >= closing || d->flags & passiveSocket)
01762     return -2;
01763   if (sockfd == -1)
01764     return -2;
01765 
01766   if (len == 0)
01767     return 0;           // what's to write?
01768 
01769   int retval;
01770 
01771   if ((d->flags & outputBufferedSocket) == 0)
01772     {
01773       // socket not buffered. Just call write
01774       retval = KSocks::self()->write(sockfd, data, len);
01775       if (retval == -1)
01776     setError(IO_WriteError, errno);
01777       else
01778     emit bytesWritten(retval);
01779     }
01780   else
01781     {
01782       // socket is buffered. Feed the write buffer
01783 
01784       // LOCK BUFFER MUTEX
01785 
01786       register unsigned wsize = writeBufferSize();
01787       if (d->outMaxSize == (int)wsize) // (int) to get rid of annoying warning
01788     {
01789       // buffer is full!
01790       setError(IO_WriteError, EWOULDBLOCK);
01791       retval = -1;
01792     }
01793       else
01794     {
01795       if (d->outMaxSize != -1 && wsize + len > (unsigned)d->outMaxSize)
01796         // we cannot write all data. Write just as much as to fill the buffer
01797         len = d->outMaxSize - wsize;
01798 
01799       // len > 0 here
01800       retval = feedWriteBuffer(len, data);
01801       if (wsize == 0 || d->emitWrite)
01802         // buffer was empty, which means that the notifier is probably disabled
01803         d->qsnOut->setEnabled(true);
01804     }
01805 
01806       // UNLOCK BUFFER MUTEX
01807     }
01808 
01809   return retval;
01810 }
01811 
01812 int KExtendedSocket::peekBlock(char *data, uint maxlen)
01813 {
01814   if (d->status < connected || d->flags & passiveSocket)
01815     return -2;
01816   if (sockfd == -1)
01817     return -2;
01818 
01819   // need to LOCK MUTEX around this call...
01820 
01821   if (d->flags & inputBufferedSocket)
01822     return consumeReadBuffer(maxlen, data, false);
01823 
01824   return 0;
01825 }
01826 
01827 int KExtendedSocket::unreadBlock(const char *, uint)
01828 {
01829   // Always return -1, indicating this is not supported
01830   setError(IO_ReadError, ENOSYS);
01831   return -1;
01832 }
01833 
01834 int KExtendedSocket::bytesAvailable() const
01835 {
01836   if (d->status < connected || d->flags & passiveSocket)
01837     return -2;
01838 
01839   // as of now, we don't do any extra processing
01840   // we only work in input-buffered sockets
01841   if (d->flags & inputBufferedSocket)
01842     return KBufferedIO::bytesAvailable();
01843 
01844   return 0;         // TODO: FIONREAD ioctl
01845 }
01846 
01847 int KExtendedSocket::waitForMore(int msecs)
01848 {
01849   cleanError();
01850   if (d->flags & passiveSocket || d->status < connected || d->status >= closing)
01851     return -2;
01852   if (sockfd == -1)
01853     return -2;
01854 
01855   fd_set rd;
01856   FD_ZERO(&rd);
01857   FD_SET(sockfd, &rd);
01858   timeval tv;
01859   tv.tv_sec = msecs / 1000;
01860   tv.tv_usec = (msecs % 1000) * 1000;
01861 
01862   int retval = KSocks::self()->select(sockfd + 1, &rd, NULL, NULL, &tv);
01863   if (retval == -1)
01864     {
01865       setError(IO_FatalError, errno);
01866       return -1;
01867     }
01868   else if (retval != 0)
01869     socketActivityRead();   // do read processing
01870 
01871   return bytesAvailable();
01872 }
01873 
01874 int KExtendedSocket::getch()
01875 {
01876   unsigned char c;
01877   int retval;
01878   retval = readBlock((char*)&c, sizeof(c));
01879 
01880   if (retval < 0)
01881     return retval;
01882   return c;
01883 }
01884 
01885 int KExtendedSocket::putch(int ch)
01886 {
01887   unsigned char c = (char)ch;
01888   return writeBlock((char*)&c, sizeof(c));
01889 }
01890 
01891 int KExtendedSocket::doLookup(const QString &host, const QString &serv, addrinfo &hint,
01892                   kde_addrinfo** res)
01893 {
01894   int err;
01895 
01896   QCString _host;
01897   QCString _serv;
01898   if (!host.isNull())
01899     _host = KIDNA::toAsciiCString(host);
01900   if (!serv.isNull())
01901     _serv = serv.latin1();
01902   // Please read the comments before kde_getaddrinfo in netsupp.cpp
01903   // for the reason we're using it
01904   err = kde_getaddrinfo(_host, _serv, &hint, res);
01905 
01906 #ifdef HAVE_RES_INIT
01907   if (err == EAI_NONAME || err == EAI_NODATA || err == EAI_AGAIN)
01908     {
01909       // A loookup error occurred and nothing was resolved
01910       // However, since the user could have just dialed up to the ISP
01911       // and new nameservers were written to /etc/resolv.conf, we have
01912       // to re-parse that
01913       res_init();
01914 
01915       // Now try looking up again
01916       err = kde_getaddrinfo(_host, _serv, &hint, res);
01917     }
01918 #endif
01919 
01920   return err;
01921 }
01922 
01923 // sets the emission of the readyRead signal
01924 void KExtendedSocket::enableRead(bool enable)
01925 {
01926   // check if we can disable the socket notifier
01927   // saves us a few cycles
01928   // this is so because in buffering mode, we rely on these signals
01929   // being emitted to do our I/O. We couldn't disable them here
01930   if (!enable && (d->flags & inputBufferedSocket) == 0 && d->qsnIn)
01931     d->qsnIn->setEnabled(false);
01932   else if (enable && d->qsnIn)
01933     // we can enable it always
01934     d->qsnIn->setEnabled(true);
01935   d->emitRead = enable;
01936 }
01937 
01938 // sets the emission of the readyWrite signal
01939 void KExtendedSocket::enableWrite(bool enable)
01940 {
01941   // same thing as above
01942   if (!enable && (d->flags & outputBufferedSocket) == 0 && d->qsnOut)
01943     d->qsnOut->setEnabled(false);
01944   else if (enable && d->qsnOut)
01945     // we can enable it always
01946     d->qsnOut->setEnabled(true);
01947   d->emitWrite = enable;
01948 }
01949 
01950 // protected slot
01951 // this is connected to d->qsnIn::activated(int)
01952 void KExtendedSocket::socketActivityRead()
01953 {
01954   if (d->flags & passiveSocket)
01955     {
01956       emit readyAccept();
01957       return;
01958     }
01959   if (d->status == connecting)
01960     {
01961       connectionEvent();
01962       return;
01963     }
01964   if (d->status != connected)
01965     return;
01966 
01967   // do we need to do I/O here?
01968   if (d->flags & inputBufferedSocket)
01969     {
01970       // aye. Do read from the socket and feed our buffer
01971       QByteArray a;
01972       char buf[1024];
01973       int len, totalread = 0;
01974 
01975       // LOCK MUTEX
01976 
01977       unsigned cursize = readBufferSize();
01978 
01979       if (d->inMaxSize == -1 || cursize < (unsigned)d->inMaxSize)
01980     {
01981       do
01982         {
01983           // check that we can read that many bytes
01984           if (d->inMaxSize != -1 && d->inMaxSize - (cursize + totalread) < sizeof(buf))
01985         // no, that would overrun the buffer
01986         // note that this will also make us exit the loop
01987         len = d->inMaxSize - (cursize + totalread);
01988           else
01989         len = sizeof(buf);
01990 
01991           len = KSocks::self()->read(sockfd, buf, len);
01992           if (len > 0)
01993         {
01994           // normal read operation
01995           a.resize(a.size() + len);
01996           memcpy(a.data() + totalread, buf, len);
01997           totalread += len; // totalread == a.size() now
01998         }
01999           else if (len == 0)
02000         {
02001           // EOF condition here
02002           ::close(sockfd);
02003           sockfd = -1;  // we're closed
02004           d->qsnIn->deleteLater();
02005           delete d->qsnOut;
02006           d->qsnIn = d->qsnOut = NULL;
02007           d->status = done;
02008           emit closed(involuntary |
02009                   (readBufferSize() ? availRead : 0) |
02010                   (writeBufferSize() ? dirtyWrite : 0));
02011           return;
02012         }
02013           else
02014         {
02015           // error!
02016           setError(IO_ReadError, errno);
02017           return;
02018         }
02019           // will loop only for normal read operations
02020         }
02021       while (len == sizeof(buf));
02022 
02023       feedReadBuffer(a.size(), a.data());
02024     }
02025 
02026       // UNLOCK MUTEX
02027     }
02028   else
02029     {
02030       // No input buffering, but the notifier fired
02031       // That means that either there is data to be read or that the 
02032       // socket closed.
02033 
02034       // try to read one byte. If we can't, then the socket got closed
02035 
02036       char c;
02037       int len = KSocks::self()->recv(sockfd, &c, sizeof(c), MSG_PEEK);
02038       if (len == 0)
02039     {
02040       // yes, it's an EOF condition
02041       d->qsnIn->setEnabled(false);
02042       ::close(sockfd);
02043       sockfd = -1;
02044       d->status = done;
02045       emit closed(involuntary);
02046       return;
02047     }
02048     }
02049 
02050   if (d->emitRead)
02051     emit readyRead();
02052 }
02053 
02054 void KExtendedSocket::socketActivityWrite()
02055 {
02056   if (d->flags & passiveSocket)
02057     return;
02058   if (d->status == connecting)
02059     {
02060       connectionEvent();
02061       return;
02062     }
02063   if (d->status != connected && d->status != closing)
02064     return;
02065 
02066   flush();
02067 
02068   bool empty = writeBufferSize() == 0;
02069 
02070   if (d->emitWrite && empty)
02071     emit readyWrite();
02072   else if (!d->emitWrite)
02073     {
02074       // check if we can disable the notifier
02075       d->qsnOut->setEnabled(!empty); // leave it enabled only if we have more data to send
02076     }
02077   if (d->status == closing && empty)
02078     {
02079       // done sending the missing data!
02080       d->status = done;
02081 
02082       delete d->qsnOut;
02083       ::close(sockfd);
02084 
02085       d->qsnOut = NULL;
02086       sockfd = -1;
02087       emit closed(delayed | (readBufferSize() ? availRead : 0));
02088     }
02089 }
02090 
02091 // this function is called whenever we have a "connection event"
02092 // that is, whenever our asynchronously connecting socket throws
02093 // an event
02094 void KExtendedSocket::connectionEvent()
02095 {
02096   if (d->status != connecting)
02097     return;         // move along. There's nothing to see here
02098   if (d->resolution == 0 || d->resolution->data == 0)
02099     {
02100       // We have a problem! Abort?
02101       kdError(170) << "KExtendedSocket::connectionEvent() called but no data available!\n";
02102       return;
02103     }
02104 
02105   int errcode = 0;
02106 
02107   if (sockfd != -1)
02108     {
02109       // our socket has activity
02110       // find out what it was
02111       int retval;
02112       socklen_t len = sizeof(errcode);
02113       retval = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (char*)&errcode, &len);
02114 
02115       if (retval == -1 || errcode != 0)
02116     {
02117       // socket activity and there was error?
02118       // that means the socket probably did not connect
02119       if (d->qsnIn)
02120         delete d->qsnIn;
02121       if (d->qsnOut)
02122         delete d->qsnOut;
02123       ::close(sockfd);
02124 
02125       sockfd = -1;
02126       d->qsnIn = d->qsnOut = NULL;
02127       setError(IO_ConnectError, errcode);
02128     }
02129       else
02130     {
02131       // hmm, socket activity and there was no error?
02132       // that means it connected
02133       // YAY!
02134       cleanError();
02135       d->status = connected;
02136       setBlockingMode(true);
02137       setFlags(IO_Sequential | IO_Raw | IO_ReadWrite | IO_Open | IO_Async);
02138       setBufferSize(d->flags & inputBufferedSocket ? -1 : 0,
02139             d->flags & outputBufferedSocket ? -1 : 0);
02140       emit connectionSuccess();
02141       return;
02142     }
02143     }
02144 
02145   // ok, we have to try something here
02146   // and sockfd == -1
02147   addrinfo *p, *q = NULL;
02148   if (d->current == 0)
02149     p = d->current = d->resolution->data;
02150   else
02151     p = d->current->ai_next;
02152   if (d->bindres)
02153     q = d->bindres->data;
02154   for ( ; p; p = p->ai_next)
02155     {
02156       // same code as in connect()
02157       if (q != NULL)
02158     {
02159       if (q->ai_family != d->current->ai_family)
02160         // differing families, scan bindres for a matching family
02161         for (q = d->bindres->data; q; q = q->ai_next)
02162           if (q->ai_family == p->ai_family)
02163         break;
02164 
02165       if (q == NULL || q->ai_family != p->ai_family)
02166         {
02167           // no matching families for this
02168           q = d->bindres->data;
02169           continue;
02170         }
02171 
02172       errno = 0;
02173       sockfd = ::socket(p->ai_family, p->ai_socktype, p->ai_protocol);
02174       setError(IO_ConnectError, errno);
02175       errcode = errno;
02176       if (sockfd == -1)
02177         continue;       // cannot create this socket
02178           fcntl(sockfd, F_SETFD, FD_CLOEXEC);
02179       if (d->addressReusable)
02180         setAddressReusable(sockfd, true);
02181       setIPv6Only(d->ipv6only);
02182       cleanError();
02183       if (KSocks::self()->bind(sockfd, q->ai_addr, q->ai_addrlen) == -1)
02184         {
02185           ::close(sockfd);
02186           sockfd = -1;
02187           continue;
02188         }
02189     }
02190       else
02191     {
02192       // no need to bind, just create
02193       sockfd = ::socket(p->ai_family, p->ai_socktype, p->ai_protocol);
02194       if (sockfd == -1)
02195         {
02196           setError(IO_ConnectError, errno);
02197           errcode = errno;
02198           continue;
02199         }
02200           fcntl(sockfd, F_SETFD, FD_CLOEXEC);
02201       if (d->addressReusable)
02202         setAddressReusable(sockfd, true);
02203       setIPv6Only(d->ipv6only);
02204       cleanError();
02205     }
02206 
02207       if (KSocks::self()->hasWorkingAsyncConnect())
02208         setBlockingMode(false);
02209       if (KSocks::self()->connect(sockfd, p->ai_addr, p->ai_addrlen) == -1)
02210     {
02211       if (errno != EWOULDBLOCK && errno != EINPROGRESS)
02212         {
02213           setError(IO_ConnectError, errno);
02214           ::close(sockfd);
02215           sockfd = -1;
02216           errcode = errno;
02217           continue;
02218         }
02219 
02220       // error here is either EWOULDBLOCK or EINPROGRESS
02221       // so, it is a good condition
02222       d->qsnIn = new QSocketNotifier(sockfd, QSocketNotifier::Read);
02223       QObject::connect(d->qsnIn, SIGNAL(activated(int)), this, SLOT(socketActivityRead()));
02224       d->qsnOut = new QSocketNotifier(sockfd, QSocketNotifier::Write);
02225       QObject::connect(d->qsnOut, SIGNAL(activated(int)), this, SLOT(socketActivityWrite()));
02226 
02227       // ok, let the Qt event loop do the selecting for us
02228       // just make sure we know where to go on in the next iteration
02229       d->current = p;
02230       return;
02231     }
02232 
02233       // eh, what?
02234       // the non-blocking socket returned valid connection?
02235       // already?
02236       // I suppose that could happen...
02237       cleanError();
02238       d->status = connected;
02239       setBlockingMode(true);
02240       setFlags(IO_Sequential | IO_Raw | IO_ReadWrite | IO_Open | IO_Async);
02241       setBufferSize(d->flags & inputBufferedSocket ? -1 : 0,
02242             d->flags & outputBufferedSocket ? -1 : 0);
02243       emit connectionSuccess();
02244       return;
02245     }
02246 
02247   // if we got here, it means that there are no more options to connect
02248   d->status = lookupDone;   // go back
02249   emit connectionFailed(errcode);
02250 }
02251 
02252 void KExtendedSocket::dnsResultsReady()
02253 {
02254   // check that this function was called in a valid state
02255   if (d->status != lookupInProgress)
02256     return;
02257 
02258   // valid state. Are results fully ready?
02259   if ((d->dns != NULL && d->dns->isWorking()) ||
02260       (d->dnsLocal != NULL && d->dnsLocal->isWorking()))
02261     // no, still waiting for answer in one of the lookups
02262     return;
02263 
02264   // ok, we have all results
02265   // count how many results we have
02266   int n = 0;
02267   addrinfo *p;
02268 
02269   if (d->dns)
02270     {
02271       d->resolution = d->dns->results();
02272       for (p = d->resolution->data; p; p = p->ai_next)
02273     n++;
02274     }
02275 
02276   if (d->dnsLocal)
02277     {
02278       d->bindres = d->dnsLocal->results();
02279       for (p = d->bindres->data; p; p = p->ai_next)
02280     n++;
02281     }
02282 
02283   if (n)
02284     {
02285       d->status = lookupDone;
02286       cleanError();
02287     }
02288   else
02289     {
02290       d->status = nothing;
02291       setError(IO_LookupError, EAI_NODATA);
02292     }
02293 
02294   emit lookupFinished(n);
02295 
02296   return;
02297 }
02298 
02299 void KExtendedSocket::startAsyncConnectSlot()
02300 {
02301   QObject::disconnect(this, SIGNAL(lookupFinished(int)), this, SLOT(startAsyncConnectSlot()));
02302 
02303   if (d->status == lookupDone)
02304     startAsyncConnect();
02305 }
02306 
02307 int KExtendedSocket::resolve(sockaddr *sock, ksocklen_t len, QString &host,
02308                  QString &port, int flags)
02309 {
02310   int err;
02311   char h[NI_MAXHOST], s[NI_MAXSERV];
02312 
02313   h[0] = s[0] = '\0';
02314 
02315   err = getnameinfo(sock, len, h, sizeof(h) - 1, s, sizeof(s) - 1, flags);
02316   host = QString::fromUtf8(h);
02317   port = QString::fromUtf8(s);
02318 
02319   return err;
02320 }
02321 
02322 int KExtendedSocket::resolve(KSocketAddress *sock, QString &host, QString &port,
02323                  int flags)
02324 {
02325   return resolve(sock->data, sock->datasize, host, port, flags);
02326 }
02327 
02328 QPtrList<KAddressInfo> KExtendedSocket::lookup(const QString& host, const QString& port,
02329                         int flags, int *error)
02330 {
02331   int err;
02332   addrinfo hint, *p;
02333   kde_addrinfo *res;
02334   QPtrList<KAddressInfo> l;
02335 
02336   memset(&hint, 0, sizeof(hint));
02337   if (!process_flags(flags, hint))
02338     {
02339       if (error)
02340     *error = EAI_BADFLAGS;
02341       return l;
02342     }
02343 
02344 //  kdDebug(170) << "Performing lookup on " << host << "|" << port << endl;
02345   err = doLookup(host, port, hint, &res);
02346   if (err)
02347     {
02348       if (error)
02349     *error = err;
02350       return l;
02351     }
02352 
02353   for (p = res->data; p; p = p->ai_next)
02354     if (valid_family(p, flags))
02355       {
02356     KAddressInfo *ai = new KAddressInfo(p);
02357 
02358 //  kdDebug(170) << "Using socket " << pretty_sock(p) << endl;
02359     l.append(ai);
02360       }
02361 
02362   if ( error )
02363       *error = 0;               // all is fine!
02364 
02365   kde_freeaddrinfo(res);    // this one we know where it came from
02366   return l;
02367 }
02368 
02369 KSocketAddress *KExtendedSocket::localAddress(int fd)
02370 {
02371   KSocketAddress *local;
02372   struct sockaddr static_sa, *sa = &static_sa;
02373   ksocklen_t len = sizeof(static_sa);
02374 
02375   /* find out the socket length, in advance
02376    * we use a sockaddr allocated on the heap just not to pass down
02377    * a NULL pointer to the first call. Some systems are reported to
02378    * set len to 0 if we pass NULL as the sockaddr */
02379   if (KSocks::self()->getsockname(fd, sa, &len) == -1)
02380     return NULL;        // error!
02381 
02382   /* was it enough? */
02383   if (len > sizeof(static_sa)
02384 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
02385       || sa->sa_len > sizeof(static_sa)
02386 #endif
02387       )
02388     {
02389       /* nope, malloc a new socket with the proper size */
02390 
02391 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
02392       if (sa->sa_len != len)
02393         len = sa->sa_len;
02394 #endif
02395 
02396       sa = (sockaddr*)malloc(len);
02397       if (sa == NULL)
02398     return NULL;        // out of memory
02399 
02400       if (KSocks::self()->getsockname(fd, sa, &len) == -1)
02401     {
02402       free(sa);
02403       return NULL;
02404     }
02405 
02406       local = KSocketAddress::newAddress(sa, len);
02407       free(sa);
02408     }
02409   else
02410     local = KSocketAddress::newAddress(sa, len);
02411 
02412   return local;
02413 }
02414 
02415 /* This is exactly the same code as localAddress, except
02416  * we call getpeername here */
02417 KSocketAddress *KExtendedSocket::peerAddress(int fd)
02418 {
02419   KSocketAddress *peer;
02420   struct sockaddr static_sa, *sa = &static_sa;
02421   ksocklen_t len = sizeof(static_sa);
02422 
02423   /* find out the socket length, in advance
02424    * we use a sockaddr allocated on the heap just not to pass down
02425    * a NULL pointer to the first call. Some systems are reported to
02426    * set len to 0 if we pass NULL as the sockaddr */
02427   if (KSocks::self()->getpeername(fd, sa, &len) == -1)
02428     return NULL;        // error!
02429 
02430   /* was it enough? */
02431   if (len > sizeof(static_sa)
02432 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
02433       || sa->sa_len > sizeof(static_sa)
02434 #endif
02435       )
02436     {
02437       /* nope, malloc a new socket with the proper size */
02438 
02439 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
02440       if (sa->sa_len != len)
02441         len = sa->sa_len;
02442 #endif
02443 
02444       sa = (sockaddr*)malloc(len);
02445       if (sa == NULL)
02446     return NULL;        // out of memory
02447 
02448       if (KSocks::self()->getpeername(fd, sa, &len) == -1)
02449     {
02450       free(sa);
02451       return NULL;
02452     }
02453 
02454       peer = KSocketAddress::newAddress(sa, len);
02455       free(sa);
02456     }
02457   else
02458     peer = KSocketAddress::newAddress(sa, len);
02459 
02460   return peer;
02461 }
02462 
02463 QString KExtendedSocket::strError(int code, int syserr)
02464 {
02465   const char * msg;
02466   if (code == IO_LookupError)
02467     msg = gai_strerror(syserr);
02468   else
02469     msg = strerror(syserr);
02470 
02471   return QString::fromLocal8Bit(msg);
02472 }
02473 
02474 
02475 QSocketNotifier *KExtendedSocket::readNotifier() { return d->qsnIn; }
02476 QSocketNotifier *KExtendedSocket::writeNotifier() { return d->qsnOut; }
02477 
02478 /*
02479  * class KAddressInfo
02480  */
02481 
02482 KAddressInfo::KAddressInfo(addrinfo *p)
02483 {
02484    ai = (addrinfo *) malloc(sizeof(addrinfo));
02485    memcpy(ai, p, sizeof(addrinfo));
02486    ai->ai_next = NULL;
02487    if (p->ai_canonname)
02488    {
02489       ai->ai_canonname = (char *) malloc(strlen(p->ai_canonname)+1);
02490       strcpy(ai->ai_canonname, p->ai_canonname);
02491    }
02492    if (p->ai_addr && p->ai_addrlen)
02493    {
02494       ai->ai_addr = (struct sockaddr *) malloc(p->ai_addrlen);
02495       memcpy(ai->ai_addr, p->ai_addr, p->ai_addrlen);
02496    }
02497    else
02498    {
02499       ai->ai_addr = 0;
02500       ai->ai_addrlen = 0;
02501    }
02502 
02503    addr = KSocketAddress::newAddress(ai->ai_addr, ai->ai_addrlen);
02504 }
02505 
02506 KAddressInfo::~KAddressInfo()
02507 {
02508   if (ai && ai->ai_canonname)
02509     free(ai->ai_canonname);
02510 
02511   if (ai && ai->ai_addr)
02512     free(ai->ai_addr);  
02513 
02514   if (ai)
02515     free(ai);
02516   delete addr;
02517 }
02518 
02519 int KAddressInfo::flags() const
02520 {
02521   return ai->ai_flags;
02522 }
02523 
02524 int KAddressInfo::family() const
02525 {
02526   return ai->ai_family;
02527 }
02528 
02529 int KAddressInfo::socktype() const
02530 {
02531   return ai->ai_socktype;
02532 }
02533 
02534 int KAddressInfo::protocol() const
02535 {
02536   return ai->ai_protocol;
02537 }
02538 
02539 const char* KAddressInfo::canonname() const
02540 {
02541   return ai->ai_canonname;
02542 }
02543 
02544 void KExtendedSocket::virtual_hook( int id, void* data )
02545 { KBufferedIO::virtual_hook( id, data ); }
02546 
02547 #include "kextsock.moc"
02548 #include "kextsocklookup.moc"
KDE Logo
This file is part of the documentation for kdecore Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Apr 21 18:42:56 2004 by doxygen 1.3.6-20040222 written by Dimitri van Heesch, © 1997-2003