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