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