kdecore Library API Documentation

kextsock.cpp

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