kextsock.cpp Source File (kdecore Library)

| # kdecore Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Source Files

# kextsock.cpp

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

This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Jan 28 12:46:29 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001