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