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