00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
00061
00062 #define CLOBBER_IN6
00063 #endif
00064 #include "netsupp.h"
00065
00066 #include "kextsocklookup.h"
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077 #ifndef AI_NUMERICHOST
00078
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
00089
00090
00091 class KExtendedSocketPrivate
00092 {
00093 public:
00094 int flags;
00095 int status;
00096 int syserror;
00097
00098 timeval timeout;
00099 QString host;
00100 QString service;
00101 QString localhost;
00102 QString localservice;
00103 kde_addrinfo *resolution;
00104 kde_addrinfo *bindres;
00105 addrinfo *current;
00106
00107 KSocketAddress *local;
00108 KSocketAddress *peer;
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
00134
00135 case KExtendedSocket::streamSocket:
00136
00137 hint.ai_socktype = SOCK_STREAM;
00138 break;
00139
00140 case KExtendedSocket::datagramSocket:
00141
00142 hint.ai_socktype = SOCK_DGRAM;
00143 break;
00144
00145 case KExtendedSocket::rawSocket:
00146
00147 hint.ai_socktype = SOCK_RAW;
00148 break;
00149
00150 default:
00151
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
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;
00179 if (flags & 0xf00 && (flags & 0x100) == 0)
00180 return false;
00181 }
00182 #ifdef PF_INET6
00183 else if (p->ai_family == PF_INET6)
00184 {
00185 if (flags & 0x0e && (flags & 0x4) == 0)
00186 return false;
00187 if (flags & 0xf00 && (flags & 0x200) == 0)
00188 return false;
00189 }
00190 #endif
00191 else if (p->ai_family == PF_UNIX)
00192 {
00193 if (flags & 0x0e && (flags & 0x2) == 0)
00194 return false;
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;
00202
00203
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
00243
00244
00245
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
00268
00269
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
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;
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;
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
00404
00405
00406
00407 KExtendedSocket::KExtendedSocket() :
00408 sockfd(-1), d(new KExtendedSocketPrivate)
00409 {
00410 }
00411
00412
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
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
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
00481
00482
00483 int KExtendedSocket::setSocketFlags(int flags)
00484 {
00485 if (d->status > nothing)
00486 return -1;
00487
00488 return d->flags = flags;
00489 }
00490
00491 int KExtendedSocket::socketFlags() const
00492 {
00493 return d->flags;
00494 }
00495
00496
00497
00498
00499
00500 bool KExtendedSocket::setHost(const QString& host)
00501 {
00502 if (d->status > nothing)
00503 return false;
00504
00505 d->host = host;
00506 return true;
00507 }
00508
00509
00510
00511
00512 QString KExtendedSocket::host() const
00513 {
00514 return d->host;
00515 }
00516
00517
00518
00519
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;
00530
00531 d->service = service;
00532 return true;
00533 }
00534
00535
00536
00537
00538 QString KExtendedSocket::port() const
00539 {
00540 return d->service;
00541 }
00542
00543
00544
00545
00546 bool KExtendedSocket::setAddress(const QString& host, int port)
00547 {
00548 return setHost(host) && setPort(port);
00549 }
00550
00551
00552
00553
00554 bool KExtendedSocket::setAddress(const QString& host, const QString& serv)
00555 {
00556 return setHost(host) && setPort(serv);
00557 }
00558
00559
00560
00561
00562
00563
00564 bool KExtendedSocket::setBindHost(const QString& host)
00565 {
00566 if (d->status > nothing || d->flags & passiveSocket)
00567 return false;
00568
00569 d->localhost = host;
00570 return true;
00571 }
00572
00573
00574
00575
00576
00577 bool KExtendedSocket::unsetBindHost()
00578 {
00579 if (d->status > nothing || d->flags & passiveSocket)
00580 return false;
00581
00582 d->localhost.truncate(0);
00583 return true;
00584 }
00585
00586
00587
00588
00589 QString KExtendedSocket::bindHost() const
00590 {
00591 return d->localhost;
00592 }
00593
00594
00595
00596
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;
00607
00608 d->localservice = service;
00609 return true;
00610 }
00611
00612
00613
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
00626
00627 QString KExtendedSocket::bindPort() const
00628 {
00629 return d->localservice;
00630 }
00631
00632
00633
00634
00635 bool KExtendedSocket::setBindAddress(const QString& host, int port)
00636 {
00637 return setBindHost(host) && setBindPort(port);
00638 }
00639
00640
00641
00642
00643 bool KExtendedSocket::setBindAddress(const QString& host, const QString& service)
00644 {
00645 return setBindHost(host) && setBindPort(service);
00646 }
00647
00648
00649
00650
00651 bool KExtendedSocket::unsetBindAddress()
00652 {
00653 return unsetBindHost() && unsetBindPort();
00654 }
00655
00656
00657
00658
00659 bool KExtendedSocket::setTimeout(int secs, int usecs)
00660 {
00661 if (d->status >= connected)
00662 return false;
00663
00664 d->timeout.tv_sec = secs;
00665 d->timeout.tv_usec = usecs;
00666 return true;
00667 }
00668
00669
00670
00671
00672 timeval KExtendedSocket::timeout() const
00673 {
00674 return d->timeout;
00675 }
00676
00677
00678
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;
00688
00689 int fdflags = fcntl(sockfd, F_GETFL, 0);
00690 if (fdflags == -1)
00691 return false;
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
00708
00709 bool KExtendedSocket::blockingMode()
00710 {
00711 cleanError();
00712 if (d->status < created)
00713 return false;
00714
00715 if (sockfd == -1)
00716 return false;
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;
00725 }
00726
00727
00728
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;
00754
00755 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof(on)) == -1)
00756 return false;
00757 return true;
00758 }
00759
00760
00761
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
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;
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
00808 d->ipv6only = enable;
00809
00810 setError(IO_UnspecifiedError, ENOSYS);
00811 return false;
00812 #endif
00813 }
00814
00815
00816
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
00839 setError(IO_UnspecifiedError, ENOSYS);
00840 return false;
00841 #endif
00842 }
00843
00844
00845
00846
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;
00859
00860 if (rsize < -2)
00861 return false;
00862
00863 if (wsize < -2)
00864 return false;
00865
00866
00867
00868 if (rsize == 0 && d->flags & inputBufferedSocket)
00869 {
00870
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
00881 if (rsize)
00882 d->flags |= inputBufferedSocket;
00883 d->inMaxSize = rsize;
00884
00885 if (rsize > 0 && (unsigned)rsize < readBufferSize())
00886
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
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
00908 if (wsize)
00909 d->flags |= outputBufferedSocket;
00910 d->outMaxSize = wsize;
00911
00912 if (wsize > 0 && (unsigned)wsize < writeBufferSize())
00913
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
00921
00922
00923 }
00924 }
00925
00926
00927
00928 setFlags((mode() & ~IO_Raw) | ((d->flags & bufferedSocket) ? 0 : IO_Raw));
00929
00930
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
00947
00948
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
00962
00963
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
00977
00978 int KExtendedSocket::lookup()
00979 {
00980 cleanError();
00981 if (d->status >= lookupInProgress)
00982 return EAI_BADFLAGS;
00983
00984 addrinfo hint;
00985
00986 memset(&hint, 0, sizeof(hint));
00987 hint.ai_family = AF_UNSPEC;
00988
00989
00990 if (d->resolution == NULL)
00991 {
00992
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
01007 hint.ai_flags |= AI_PASSIVE;
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
01023
01024 int KExtendedSocket::startAsyncLookup()
01025 {
01026 cleanError();
01027 if (d->status > lookupInProgress)
01028 return -1;
01029 if (d->status == lookupInProgress)
01030
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;
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
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
01087 if (n)
01088 d->status = lookupInProgress;
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;
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;
01128 if (!d->resolution) return -2;
01129
01130 addrinfo *p;
01131
01132
01133 for (p = d->resolution->data; p; p = p->ai_next)
01134 {
01135
01136 if (!valid_family(p, d->flags))
01137 continue;
01138
01139
01140 sockfd = ::socket(p->ai_family, p->ai_socktype, p->ai_protocol);
01141 if (sockfd == -1)
01142 {
01143
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
01161
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;
01198
01199
01200
01201
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);
01212 FD_ZERO(&set);
01213 FD_SET(sockfd, &set);
01214
01215
01216
01217
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;
01223 }
01224 else if (retval == 0 || !FD_ISSET(sockfd, &set))
01225 {
01226 setError(IO_TimeOutError, 0);
01227 return -3;
01228 }
01229 }
01230
01231
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
01243
01244 setBlockingMode(block);
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);
01251
01252 return 0;
01253 }
01254
01255
01256
01257
01258
01259
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
01274
01275
01276
01277
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
01291
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
01301 if (!valid_family(p, d->flags))
01302 continue;
01303
01304
01305 if (q != NULL)
01306 {
01307
01308 if (q->ai_family != p->ai_family)
01309
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
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;
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
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
01356 d->status = created;
01357
01358
01359 if (doingtimeout && KSocks::self()->hasWorkingAsyncConnect())
01360 {
01361 fd_set rd, wr;
01362
01363 setBlockingMode(false);
01364
01365
01366 if (KSocks::self()->connect(sockfd, p->ai_addr, p->ai_addrlen) == -1)
01367 {
01368
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;
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;
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;
01398 }
01399
01400
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
01410
01411
01412
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
01420 kdDebug(170) << "Socket " << sockfd << " did not connect: "
01421 << strerror(errcode) << endl;
01422 ::close(sockfd);
01423 sockfd = -1;
01424
01425
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;
01431 }
01432
01433 setError(IO_ConnectError, errcode);
01434 continue;
01435 }
01436 }
01437
01438
01439
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
01447 return 0;
01448 }
01449 else
01450 {
01451
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
01467 return 0;
01468 }
01469 }
01470
01471
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
01481 if (d->status >= connected || d->flags & passiveSocket)
01482 return -2;
01483
01484 if (d->status == connecting)
01485
01486 return 0;
01487
01488
01489
01490
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;
01498 }
01499
01500
01501
01502 d->status = connecting;
01503 QGuardedPtr<QObject> p = this;
01504 connectionEvent();
01505 if (!p)
01506 return -1;
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
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;
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;
01549
01550
01551 if (d->flags & outputBufferedSocket && writeBufferSize() > 0)
01552 {
01553
01554 d->status = closing;
01555 if (d->qsnIn)
01556 delete d->qsnIn;
01557 d->qsnIn = NULL;
01558
01559
01560 }
01561 else
01562 {
01563
01564
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
01576 }
01577
01578
01579 void KExtendedSocket::closeNow()
01580 {
01581 if (d->status >= done)
01582 return;
01583
01584
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
01609 sockfd = -1;
01610 d->status = done;
01611
01612
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
01633 consumeReadBuffer(readBufferSize(), NULL, true);
01634 consumeWriteBuffer(writeBufferSize());
01635
01636
01637
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;
01651
01652
01653
01654 unsigned written = 0;
01655 unsigned offset = outBufIndex;
01656 while (writeBufferSize() - written > 0)
01657 {
01658
01659
01660
01661
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
01676 int wrote = KSocks::self()->write(sockfd, buf, count);
01677
01678 if (wrote == -1)
01679 {
01680
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
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
01710
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
01724
01725
01726
01727 retval = consumeReadBuffer(maxlen, data);
01728 if (retval == 0)
01729 {
01730
01731
01732 if (sockfd == -1)
01733 return 0;
01734 setError(IO_ReadError, EWOULDBLOCK);
01735 retval = -1;
01736 }
01737
01738
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;
01754
01755 int retval;
01756
01757 if ((d->flags & outputBufferedSocket) == 0)
01758 {
01759
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
01769
01770
01771
01772 register unsigned wsize = writeBufferSize();
01773 if (d->outMaxSize == (int)wsize)
01774 {
01775
01776 setError(IO_WriteError, EWOULDBLOCK);
01777 retval = -1;
01778 }
01779 else
01780 {
01781 if (d->outMaxSize != -1 && wsize + len > (unsigned)d->outMaxSize)
01782
01783 len = d->outMaxSize - wsize;
01784
01785
01786 retval = feedWriteBuffer(len, data);
01787 if (wsize == 0 || d->emitWrite)
01788
01789 d->qsnOut->setEnabled(true);
01790 }
01791
01792
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
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
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
01826
01827 if (d->flags & inputBufferedSocket)
01828 return KBufferedIO::bytesAvailable();
01829
01830 return 0;
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();
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
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
01890
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
01897
01898
01899
01900 res_init();
01901
01902
01903 err = kde_getaddrinfo(_host, _serv, &hint, res);
01904 }
01905 #endif
01906
01907 return err;
01908 }
01909
01910
01911 void KExtendedSocket::enableRead(bool enable)
01912 {
01913
01914
01915
01916
01917 if (!enable && (d->flags & inputBufferedSocket) == 0 && d->qsnIn)
01918 d->qsnIn->setEnabled(false);
01919 else if (enable && d->qsnIn)
01920
01921 d->qsnIn->setEnabled(true);
01922 d->emitRead = enable;
01923 }
01924
01925
01926 void KExtendedSocket::enableWrite(bool enable)
01927 {
01928
01929 if (!enable && (d->flags & outputBufferedSocket) == 0 && d->qsnOut)
01930 d->qsnOut->setEnabled(false);
01931 else if (enable && d->qsnOut)
01932
01933 d->qsnOut->setEnabled(true);
01934 d->emitWrite = enable;
01935 }
01936
01937
01938
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
01955 if (d->flags & inputBufferedSocket)
01956 {
01957
01958 QByteArray a;
01959 char buf[1024];
01960 int len, totalread = 0;
01961
01962
01963
01964 unsigned cursize = readBufferSize();
01965
01966 if (d->inMaxSize == -1 || cursize < (unsigned)d->inMaxSize)
01967 {
01968 do
01969 {
01970
01971 if (d->inMaxSize != -1 && d->inMaxSize - (cursize + totalread) < sizeof(buf))
01972
01973
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
01982 a.resize(a.size() + len);
01983 memcpy(a.data() + totalread, buf, len);
01984 totalread += len;
01985 }
01986 else if (len == 0)
01987 {
01988
01989 ::close(sockfd);
01990 sockfd = -1;
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
02003 setError(IO_ReadError, errno);
02004 return;
02005 }
02006
02007 }
02008 while (len == sizeof(buf));
02009
02010 feedReadBuffer(a.size(), a.data());
02011 }
02012
02013
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
02041 d->qsnOut->setEnabled(!empty);
02042 }
02043 if (d->status == closing && empty)
02044 {
02045
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
02058
02059
02060 void KExtendedSocket::connectionEvent()
02061 {
02062 if (d->status != connecting)
02063 return;
02064 if (d->resolution == 0 || d->resolution->data == 0)
02065 {
02066
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
02076
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
02084
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
02098
02099
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
02112
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
02123 if (q != NULL)
02124 {
02125 if (q->ai_family != d->current->ai_family)
02126
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
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;
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
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
02185
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
02192
02193 d->current = p;
02194 return;
02195 }
02196
02197
02198
02199
02200
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
02212 d->status = lookupDone;
02213 emit connectionFailed(errcode);
02214 }
02215
02216 void KExtendedSocket::dnsResultsReady()
02217 {
02218
02219 if (d->status != lookupInProgress)
02220 return;
02221
02222
02223 if ((d->dns != NULL && d->dns->isWorking()) ||
02224 (d->dnsLocal != NULL && d->dnsLocal->isWorking()))
02225
02226 return;
02227
02228
02229
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
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
02310 l.append(ai);
02311 }
02312
02313 if ( error )
02314 *error = 0;
02315
02316 kde_freeaddrinfo(res);
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
02327
02328
02329
02330 if (KSocks::self()->getsockname(fd, sa, &len) == -1)
02331 return NULL;
02332
02333
02334 if (len > sizeof(static_sa)
02335 #ifdef HAVE_SOCKADDR_SA_LEN
02336 || sa->sa_len > sizeof(static_sa)
02337 #endif
02338 )
02339 {
02340
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;
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
02367
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
02375
02376
02377
02378 if (KSocks::self()->getpeername(fd, sa, &len) == -1)
02379 return NULL;
02380
02381
02382 if (len > sizeof(static_sa)
02383 #ifdef HAVE_SOCKADDR_SA_LEN
02384 || sa->sa_len > sizeof(static_sa)
02385 #endif
02386 )
02387 {
02388
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;
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
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"