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