00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <config.h>
00022
00023 #include <sys/types.h>
00024 #include <sys/socket.h>
00025 #include <sys/times.h>
00026 #include <netinet/in.h>
00027 #include <arpa/inet.h>
00028 #include <sys/un.h>
00029
00030 #include <stdio.h>
00031 #include <errno.h>
00032 #include <fcntl.h>
00033
00034 #include <netdb.h>
00035
00036 #include <stdlib.h>
00037 #include <unistd.h>
00038
00039 #include <qglobal.h>
00040 #include <qstring.h>
00041 #include <qiodevice.h>
00042 #include <qsocketnotifier.h>
00043 #include <qguardedptr.h>
00044
00045 #include "kresolver.h"
00046
00047 #include "kdebug.h"
00048 #include "kextsock.h"
00049 #include "ksockaddr.h"
00050 #include "ksocks.h"
00051
00052 #ifdef __CYGWIN__
00053 #include "netsupp.h"
00054 #endif
00055
00056 using namespace KNetwork;
00057
00058
00059
00060
00061
00062 class KExtendedSocketPrivate
00063 {
00064 public:
00065 int flags;
00066 int status;
00067 int syserror;
00068
00069 timeval timeout;
00070
00071 KResolver resRemote;
00072 KResolver resLocal;
00073 unsigned current;
00074
00075 ::KSocketAddress *local;
00076 ::KSocketAddress *peer;
00077
00078 QSocketNotifier *qsnIn, *qsnOut;
00079 int inMaxSize, outMaxSize;
00080 bool emitRead : 1, emitWrite : 1;
00081 mutable bool addressReusable : 1, ipv6only : 1;
00082
00083 KExtendedSocketPrivate() :
00084 flags(0), status(0), syserror(0),
00085 current(0), local(0), peer(0),
00086 qsnIn(0), qsnOut(0), inMaxSize(-1), outMaxSize(-1), emitRead(false), emitWrite(false),
00087 addressReusable(false), ipv6only(false)
00088 {
00089 timeout.tv_sec = timeout.tv_usec = 0;
00090 }
00091 };
00092
00093
00094 static bool process_flags(int flags, int& socktype, int& familyMask, int& outflags)
00095 {
00096 switch (flags & (KExtendedSocket::streamSocket | KExtendedSocket::datagramSocket | KExtendedSocket::rawSocket))
00097 {
00098 case 0:
00099
00100
00101 case KExtendedSocket::streamSocket:
00102
00103 socktype = SOCK_STREAM;
00104 break;
00105
00106 case KExtendedSocket::datagramSocket:
00107
00108 socktype = SOCK_DGRAM;
00109 break;
00110
00111 case KExtendedSocket::rawSocket:
00112
00113 socktype = SOCK_RAW;
00114 break;
00115
00116 default:
00117
00118 return false;
00119 }
00120
00121 if (flags & KExtendedSocket::knownSocket)
00122 {
00123 familyMask = 0;
00124 if ((flags & KExtendedSocket::unixSocket) == KExtendedSocket::unixSocket)
00125 familyMask |= KResolver::UnixFamily;
00126
00127 switch ((flags & (KExtendedSocket::ipv6Socket|KExtendedSocket::ipv4Socket)))
00128 {
00129 case KExtendedSocket::ipv4Socket:
00130 familyMask |= KResolver::IPv4Family;
00131 break;
00132 case KExtendedSocket::ipv6Socket:
00133 familyMask |= KResolver::IPv6Family;
00134 break;
00135 case KExtendedSocket::inetSocket:
00136 familyMask |= KResolver::InternetFamily;
00137 break;
00138 }
00139
00140
00141 }
00142 else
00143 familyMask = KResolver::KnownFamily;
00144
00145
00146 outflags = (flags & KExtendedSocket::passiveSocket ? KResolver::Passive : 0) |
00147 (flags & KExtendedSocket::canonName ? KResolver::CanonName : 0) |
00148 (flags & KExtendedSocket::noResolve ? KResolver::NoResolve : 0);
00149
00150 if (getenv("KDE_NO_IPV6"))
00151 familyMask &= ~KResolver::IPv6Family;
00152
00153 return true;
00154 }
00155
00156
00157
00158
00159
00160 static int skipData(int fd, unsigned len)
00161 {
00162 char buf[1024];
00163 unsigned skipped = 0;
00164 while (len)
00165 {
00166 int count = sizeof(buf);
00167 if ((unsigned)count > len)
00168 count = len;
00169 count = KSocks::self()->read(fd, buf, count);
00170 if (count == -1)
00171 return -1;
00172 else
00173 {
00174 len -= count;
00175 skipped += count;
00176 }
00177 }
00178 return skipped;
00179 }
00180
00181
00182
00183
00184
00185
00186 KExtendedSocket::KExtendedSocket() :
00187 sockfd(-1), d(new KExtendedSocketPrivate)
00188 {
00189 }
00190
00191
00192 KExtendedSocket::KExtendedSocket(const QString& host, int port, int flags) :
00193 sockfd(-1), d(new KExtendedSocketPrivate)
00194 {
00195 setAddress(host, port);
00196 setSocketFlags(flags);
00197 }
00198
00199
00200 KExtendedSocket::KExtendedSocket(const QString& host, const QString& service, int flags) :
00201 sockfd(-1), d(new KExtendedSocketPrivate)
00202 {
00203 setAddress(host, service);
00204 setSocketFlags(flags);
00205 }
00206
00207
00208 KExtendedSocket::~KExtendedSocket()
00209 {
00210 closeNow();
00211
00212 if (d->local != NULL)
00213 delete d->local;
00214 if (d->peer != NULL)
00215 delete d->peer;
00216
00217 if (d->qsnIn != NULL)
00218 delete d->qsnIn;
00219 if (d->qsnOut != NULL)
00220 delete d->qsnOut;
00221
00222 delete d;
00223 }
00224
00225 void KExtendedSocket::reset()
00226 {
00227 closeNow();
00228 release();
00229 d->current = 0;
00230 d->status = nothing;
00231 d->syserror = 0;
00232 }
00233
00234 int KExtendedSocket::socketStatus() const
00235 {
00236 return d->status;
00237 }
00238
00239 void KExtendedSocket::setSocketStatus(int newstatus)
00240 {
00241 d->status = newstatus;
00242 }
00243
00244 void KExtendedSocket::setError(int errorcode, int syserror)
00245 {
00246 setStatus(errorcode);
00247 d->syserror = syserror;
00248 }
00249
00250 int KExtendedSocket::systemError() const
00251 {
00252 return d->syserror;
00253 }
00254
00255
00256
00257
00258
00259 int KExtendedSocket::setSocketFlags(int flags)
00260 {
00261 if (d->status > nothing)
00262 return -1;
00263
00264 return d->flags = flags;
00265 }
00266
00267 int KExtendedSocket::socketFlags() const
00268 {
00269 return d->flags;
00270 }
00271
00272
00273
00274
00275
00276 bool KExtendedSocket::setHost(const QString& host)
00277 {
00278 if (d->status > nothing)
00279 return false;
00280
00281 d->resRemote.setNodeName(host);
00282 return true;
00283 }
00284
00285
00286
00287
00288 QString KExtendedSocket::host() const
00289 {
00290 return d->resRemote.nodeName();
00291 }
00292
00293
00294
00295
00296
00297 bool KExtendedSocket::setPort(int port)
00298 {
00299 return setPort(QString::number(port));
00300 }
00301
00302 bool KExtendedSocket::setPort(const QString& service)
00303 {
00304 if (d->status > nothing)
00305 return false;
00306
00307 d->resRemote.setServiceName(service);
00308 return true;
00309 }
00310
00311
00312
00313
00314 QString KExtendedSocket::port() const
00315 {
00316 return d->resRemote.serviceName();
00317 }
00318
00319
00320
00321
00322 bool KExtendedSocket::setAddress(const QString& host, int port)
00323 {
00324 return setHost(host) && setPort(port);
00325 }
00326
00327
00328
00329
00330 bool KExtendedSocket::setAddress(const QString& host, const QString& serv)
00331 {
00332 return setHost(host) && setPort(serv);
00333 }
00334
00335
00336
00337
00338
00339
00340 bool KExtendedSocket::setBindHost(const QString& host)
00341 {
00342 if (d->status > nothing || d->flags & passiveSocket)
00343 return false;
00344
00345 d->resLocal.setServiceName(host);
00346 return true;
00347 }
00348
00349
00350
00351
00352
00353 bool KExtendedSocket::unsetBindHost()
00354 {
00355 return setBindHost(QString::null);
00356 }
00357
00358
00359
00360
00361 QString KExtendedSocket::bindHost() const
00362 {
00363 return d->resLocal.serviceName();
00364 }
00365
00366
00367
00368
00369
00370 bool KExtendedSocket::setBindPort(int port)
00371 {
00372 return setBindPort(QString::number(port));
00373 }
00374
00375 bool KExtendedSocket::setBindPort(const QString& service)
00376 {
00377 if (d->status > nothing || d->flags & passiveSocket)
00378 return false;
00379
00380 d->resLocal.setServiceName(service);
00381 return true;
00382 }
00383
00384
00385
00386
00387 bool KExtendedSocket::unsetBindPort()
00388 {
00389 return setBindPort(QString::null);
00390 }
00391
00392
00393
00394
00395 QString KExtendedSocket::bindPort() const
00396 {
00397 return d->resLocal.serviceName();
00398 }
00399
00400
00401
00402
00403 bool KExtendedSocket::setBindAddress(const QString& host, int port)
00404 {
00405 return setBindHost(host) && setBindPort(port);
00406 }
00407
00408
00409
00410
00411 bool KExtendedSocket::setBindAddress(const QString& host, const QString& service)
00412 {
00413 return setBindHost(host) && setBindPort(service);
00414 }
00415
00416
00417
00418
00419 bool KExtendedSocket::unsetBindAddress()
00420 {
00421 return unsetBindHost() && unsetBindPort();
00422 }
00423
00424
00425
00426
00427 bool KExtendedSocket::setTimeout(int secs, int usecs)
00428 {
00429 if (d->status >= connected)
00430 return false;
00431
00432 d->timeout.tv_sec = secs;
00433 d->timeout.tv_usec = usecs;
00434 return true;
00435 }
00436
00437
00438
00439
00440 timeval KExtendedSocket::timeout() const
00441 {
00442 return d->timeout;
00443 }
00444
00445
00446
00447
00448 bool KExtendedSocket::setBlockingMode(bool enable)
00449 {
00450 cleanError();
00451 if (d->status < created)
00452 return false;
00453
00454 if (sockfd == -1)
00455 return false;
00456
00457 int fdflags = fcntl(sockfd, F_GETFL, 0);
00458 if (fdflags == -1)
00459 return false;
00460
00461 if (!enable)
00462 fdflags |= O_NONBLOCK;
00463 else
00464 fdflags &= ~O_NONBLOCK;
00465
00466 if (fcntl(sockfd, F_SETFL, fdflags) == -1)
00467 {
00468 setError(IO_UnspecifiedError, errno);
00469 return false;
00470 }
00471 return true;
00472 }
00473
00474
00475
00476
00477 bool KExtendedSocket::blockingMode()
00478 {
00479 cleanError();
00480 if (d->status < created)
00481 return false;
00482
00483 if (sockfd == -1)
00484 return false;
00485
00486 int fdflags = fcntl(sockfd, F_GETFL, 0);
00487 if (fdflags == -1)
00488 {
00489 setError(IO_UnspecifiedError, errno);
00490 return false;
00491 }
00492 return (fdflags & O_NONBLOCK) == 0;
00493 }
00494
00495
00496
00497
00498 bool KExtendedSocket::setAddressReusable(bool enable)
00499 {
00500 cleanError();
00501 d->addressReusable = enable;
00502 if (d->status < created)
00503 return true;
00504
00505 if (sockfd == -1)
00506 return true;
00507
00508 if (!setAddressReusable(sockfd, enable))
00509 {
00510 setError(IO_UnspecifiedError, errno);
00511 return false;
00512 }
00513 return true;
00514 }
00515
00516 bool KExtendedSocket::setAddressReusable(int fd, bool enable)
00517 {
00518 if (fd == -1)
00519 return false;
00520
00521 int on = enable;
00522
00523 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof(on)) == -1)
00524 return false;
00525 return true;
00526 }
00527
00528
00529
00530
00531 bool KExtendedSocket::addressReusable()
00532 {
00533 cleanError();
00534 if (d->status < created)
00535 return d->addressReusable;
00536
00537 if (sockfd == -1)
00538 return d->addressReusable;
00539
00540 int on;
00541 socklen_t onsiz = sizeof(on);
00542 if (getsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char*)&on, &onsiz) == -1)
00543 {
00544 setError(IO_UnspecifiedError, errno);
00545 return false;
00546 }
00547
00548 return on != 0;
00549 }
00550
00551
00552
00553
00554 bool KExtendedSocket::setIPv6Only(bool enable)
00555 {
00556 #ifdef IPV6_V6ONLY
00557 cleanError();
00558
00559 d->ipv6only = enable;
00560 if (sockfd == -1)
00561 return true;
00562
00563 int on = enable;
00564
00565 if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY,
00566 (char *)&on, sizeof(on)) == -1)
00567 {
00568 setError(IO_UnspecifiedError, errno);
00569 return false;
00570 }
00571 else
00572 return true;
00573
00574 #else
00575
00576 d->ipv6only = enable;
00577
00578 setError(IO_UnspecifiedError, ENOSYS);
00579 return false;
00580 #endif
00581 }
00582
00583
00584
00585
00586 bool KExtendedSocket::isIPv6Only()
00587 {
00588 #ifdef IPV6_V6ONLY
00589 cleanError();
00590
00591 if (d->status < created || sockfd == -1)
00592 return d->ipv6only;
00593
00594 int on;
00595 socklen_t onsiz = sizeof(on);
00596 if (getsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY,
00597 (char *)&on, &onsiz) == -1)
00598 {
00599 setError(IO_UnspecifiedError, errno);
00600 return false;
00601 }
00602
00603 return d->ipv6only = on;
00604
00605 #else
00606
00607 setError(IO_UnspecifiedError, ENOSYS);
00608 return false;
00609 #endif
00610 }
00611
00612
00613
00614
00615
00616 bool KExtendedSocket::setBufferSize(int rsize, int wsize)
00617 {
00618 cleanError();
00619 if (d->status < created)
00620 return false;
00621
00622 if (sockfd == -1)
00623 return false;
00624
00625 if (d->flags & passiveSocket)
00626 return false;
00627
00628 if (rsize < -2)
00629 return false;
00630
00631 if (wsize < -2)
00632 return false;
00633
00634
00635
00636
00637
00638
00639 if (d->qsnIn == NULL)
00640 {
00641 d->qsnIn = new QSocketNotifier(sockfd, QSocketNotifier::Read);
00642 QObject::connect(d->qsnIn, SIGNAL(activated(int)), this, SLOT(socketActivityRead()));
00643 d->qsnIn->setEnabled(true);
00644 }
00645
00646 if (rsize == 0 && d->flags & inputBufferedSocket)
00647 {
00648
00649 d->flags &= ~inputBufferedSocket;
00650
00651 consumeReadBuffer(readBufferSize(), NULL, true);
00652 d->inMaxSize = 0;
00653 }
00654 else if (rsize != -2)
00655 {
00656
00657 if (rsize)
00658 d->flags |= inputBufferedSocket;
00659 d->inMaxSize = rsize;
00660
00661 if (rsize > 0 && (unsigned)rsize < readBufferSize())
00662
00663 consumeReadBuffer(readBufferSize() - rsize, NULL, true);
00664
00665 }
00666
00667 if (wsize == 0 && d->flags & outputBufferedSocket)
00668 {
00669
00670 d->flags &= ~outputBufferedSocket;
00671 if (d->qsnOut && !d->emitWrite)
00672 d->qsnOut->setEnabled(false);
00673 consumeWriteBuffer(writeBufferSize());
00674 d->outMaxSize = 0;
00675 }
00676 else if (wsize != -2)
00677 {
00678
00679 if (wsize)
00680 d->flags |= outputBufferedSocket;
00681 d->outMaxSize = wsize;
00682
00683 if (wsize > 0 && (unsigned)wsize < writeBufferSize())
00684
00685 consumeWriteBuffer(writeBufferSize() - wsize);
00686
00687 if (d->qsnOut == NULL)
00688 {
00689 d->qsnOut = new QSocketNotifier(sockfd, QSocketNotifier::Write);
00690 QObject::connect(d->qsnOut, SIGNAL(activated(int)), this, SLOT(socketActivityWrite()));
00691
00692
00693
00694 }
00695 }
00696
00697
00698
00699 setFlags((mode() & ~IO_Raw) | ((d->flags & bufferedSocket) ? 0 : IO_Raw));
00700
00701
00702 if (d->emitWrite && d->qsnOut == NULL)
00703 {
00704 d->qsnOut = new QSocketNotifier(sockfd, QSocketNotifier::Write);
00705 QObject::connect(d->qsnOut, SIGNAL(activated(int)), this, SLOT(socketActivityWrite()));
00706 }
00707
00708 return true;
00709 }
00710
00711
00712
00713
00714
00715
00716 const ::KSocketAddress *KExtendedSocket::localAddress()
00717 {
00718 if (d->local != NULL)
00719 return d->local;
00720 if (d->status < bound)
00721 return NULL;
00722
00723 return d->local = localAddress(sockfd);
00724 }
00725
00726
00727
00728
00729
00730
00731 const ::KSocketAddress* KExtendedSocket::peerAddress()
00732 {
00733 if (d->peer != NULL)
00734 return d->peer;
00735 if (d->flags & passiveSocket || d->status < connected)
00736 return NULL;
00737
00738 return d->peer = peerAddress(sockfd);
00739 }
00740
00741
00742
00743
00744 int KExtendedSocket::lookup()
00745 {
00746 if (startAsyncLookup() != 0)
00747 return -1;
00748
00749 if (!d->resRemote.wait() || !d->resLocal.wait())
00750 {
00751 d->status = nothing;
00752 return -1;
00753 }
00754
00755 d->status = lookupDone;
00756 if (d->resRemote.error() != KResolver::NoError)
00757 return d->resRemote.error();
00758 if (d->resLocal.error() != KResolver::NoError)
00759 return d->resLocal.error();
00760 return 0;
00761 }
00762
00763
00764
00765
00766 int KExtendedSocket::startAsyncLookup()
00767 {
00768 cleanError();
00769 if (d->status > lookupInProgress)
00770 return -1;
00771 if (d->status == lookupInProgress)
00772
00773 return 0;
00774
00775
00776 int socktype, familyMask, flags;
00777 if (!process_flags(d->flags, socktype, familyMask, flags))
00778 return -2;
00779
00780
00781 if (!d->resRemote.isRunning())
00782 {
00783 d->resRemote.setFlags(flags);
00784 d->resRemote.setFamily(familyMask);
00785 d->resRemote.setSocketType(socktype);
00786 QObject::connect(&d->resRemote, SIGNAL(finished(KResolverResults)),
00787 this, SLOT(dnsResultsReady()));
00788
00789 if (!d->resRemote.start())
00790 {
00791 setError(IO_LookupError, d->resRemote.error());
00792 return d->resRemote.error();
00793 }
00794 }
00795
00796 if ((d->flags & passiveSocket) == 0 && !d->resLocal.isRunning())
00797 {
00798
00799 flags |= KResolver::Passive;
00800 d->resLocal.setFlags(flags);
00801 d->resLocal.setFamily(familyMask);
00802 d->resLocal.setSocketType(socktype);
00803 QObject::connect(&d->resLocal, SIGNAL(finished(KResolverResults)),
00804 this, SLOT(dnsResultsReady()));
00805
00806 if (!d->resLocal.start())
00807 {
00808 setError(IO_LookupError, d->resLocal.error());
00809 return d->resLocal.error();
00810 }
00811 }
00812
00813
00814 if (d->resRemote.isRunning() || d->resLocal.isRunning())
00815 d->status = lookupInProgress;
00816 else
00817 {
00818 d->status = lookupDone;
00819 emit lookupFinished(d->resRemote.results().count() +
00820 d->resLocal.results().count());
00821 }
00822 return 0;
00823 }
00824
00825 void KExtendedSocket::cancelAsyncLookup()
00826 {
00827 cleanError();
00828 if (d->status != lookupInProgress)
00829 return;
00830
00831 d->status = nothing;
00832 d->resLocal.cancel(false);
00833 d->resRemote.cancel(false);
00834 }
00835
00836 int KExtendedSocket::listen(int N)
00837 {
00838 cleanError();
00839 if ((d->flags & passiveSocket) == 0 || d->status >= listening)
00840 return -2;
00841 if (d->status < lookupDone)
00842 if (lookup() != 0)
00843 return -2;
00844 if (d->resRemote.error())
00845 return -2;
00846
00847
00848 KResolverResults::const_iterator it;
00849 KResolverResults res = d->resRemote.results();
00850 for (it = res.begin(); it != res.end(); ++it)
00851 {
00852
00853 sockfd = ::socket((*it).family(), (*it).socketType(), (*it).protocol());
00854 if (sockfd == -1)
00855 {
00856
00857
00858 continue;
00859 }
00860
00861 fcntl(sockfd, F_SETFD, FD_CLOEXEC);
00862
00863 if (d->addressReusable)
00864 setAddressReusable(sockfd, true);
00865 setIPv6Only(d->ipv6only);
00866 cleanError();
00867 if (KSocks::self()->bind(sockfd, (*it).address().address(), (*it).length()) == -1)
00868 {
00869
00870 ::close(sockfd);
00871 sockfd = -1;
00872 continue;
00873 }
00874
00875
00876
00877
00878 d->status = bound;
00879 break;
00880 }
00881
00882 if (sockfd == -1)
00883 {
00884 setError(IO_ListenError, errno);
00885
00886 return -1;
00887 }
00888
00889 d->status = bound;
00890 setFlags(IO_Sequential | IO_Raw | IO_ReadWrite);
00891
00892 int retval = KSocks::self()->listen(sockfd, N);
00893 if (retval == -1)
00894 setError(IO_ListenError, errno);
00895 else
00896 {
00897 d->status = listening;
00898 d->qsnIn = new QSocketNotifier(sockfd, QSocketNotifier::Read);
00899 QObject::connect(d->qsnIn, SIGNAL(activated(int)), this, SLOT(socketActivityRead()));
00900 }
00901 return retval == -1 ? -1 : 0;
00902 }
00903
00904 int KExtendedSocket::accept(KExtendedSocket *&sock)
00905 {
00906 cleanError();
00907 sock = NULL;
00908 if ((d->flags & passiveSocket) == 0 || d->status >= accepting)
00909 return -2;
00910 if (d->status < listening)
00911 if (listen() < 0)
00912 return -2;
00913
00914
00915
00916
00917 bool block = blockingMode();
00918 struct sockaddr sa;
00919 ksocklen_t len = sizeof(sa);
00920 sock = NULL;
00921
00922 if (d->timeout.tv_sec > 0 || d->timeout.tv_usec > 0)
00923 {
00924 fd_set set;
00925
00926 setBlockingMode(false);
00927 FD_ZERO(&set);
00928 FD_SET(sockfd, &set);
00929
00930
00931
00932
00933 int retval = KSocks::self()->select(sockfd + 1, &set, NULL, NULL, &d->timeout);
00934 if (retval == -1)
00935 {
00936 setError(IO_UnspecifiedError, errno);
00937 return -1;
00938 }
00939 else if (retval == 0 || !FD_ISSET(sockfd, &set))
00940 {
00941 setError(IO_TimeOutError, 0);
00942 return -3;
00943 }
00944 }
00945
00946
00947 int newfd = KSocks::self()->accept(sockfd, &sa, &len);
00948
00949 if (newfd == -1)
00950 {
00951 setError(IO_AcceptError, errno);
00952 kdWarning(170) << "Error accepting on socket " << sockfd << ":"
00953 << perror << endl;
00954 return -1;
00955 }
00956
00957 fcntl(newfd, F_SETFD, FD_CLOEXEC);
00958
00959
00960
00961 setBlockingMode(block);
00962
00963 sock = new KExtendedSocket;
00964 sock->d->status = connected;
00965 sock->sockfd = newfd;
00966 sock->setFlags(IO_Sequential | IO_Raw | IO_ReadWrite | IO_Open | IO_Async);
00967 sock->setBufferSize(0, 0);
00968
00969 return 0;
00970 }
00971
00972
00973
00974
00975
00976
00977
00978 int KExtendedSocket::connect()
00979 {
00980 cleanError();
00981 if (d->flags & passiveSocket || d->status >= connected)
00982 return -2;
00983 if (d->status < lookupDone)
00984 if (lookup() != 0)
00985 return -2;
00986
00987 timeval end, now;
00988
00989
00990
00991
00992
00993
00994 bool doingtimeout = d->timeout.tv_sec > 0 || d->timeout.tv_usec > 0;
00995 if (doingtimeout)
00996 {
00997 gettimeofday(&end, NULL);
00998 end.tv_usec += d->timeout.tv_usec;
00999 end.tv_sec += d->timeout.tv_sec;
01000 if (end.tv_usec > 1000*1000)
01001 {
01002 end.tv_usec -= 1000*1000;
01003 end.tv_sec++;
01004 }
01005
01006
01007 }
01008
01009 KResolverResults remote = d->resRemote.results(),
01010 local = d->resLocal.results();
01011 KResolverResults::const_iterator it, it2;
01012
01013
01014
01015 for (it = remote.begin(), it2 = local.begin(); it != remote.end(); ++it)
01016 {
01017
01018 if (it2 != local.end())
01019 {
01020
01021 if ((*it).family() != (*it2).family())
01022
01023 for (it2 = local.begin(); it2 != local.end(); ++it2)
01024 if ((*it).family() == (*it2).family())
01025 break;
01026
01027 if ((*it).family() != (*it2).family())
01028 {
01029
01030
01031 it2 = local.begin();
01032 continue;
01033 }
01034
01035
01036 errno = 0;
01037 sockfd = ::socket((*it).family(), (*it).socketType(), (*it).protocol());
01038 setError(IO_ConnectError, errno);
01039 if (sockfd == -1)
01040 continue;
01041 fcntl(sockfd, F_SETFD, FD_CLOEXEC);
01042 if (d->addressReusable)
01043 setAddressReusable(sockfd, true);
01044 setIPv6Only(d->ipv6only);
01045 cleanError();
01046 if (KSocks::self()->bind(sockfd, (*it2).address(), (*it2).length()))
01047 {
01048
01049 ::close(sockfd);
01050 sockfd = -1;
01051 continue;
01052 }
01053 }
01054 else
01055 {
01056
01057 sockfd = ::socket((*it).family(), (*it).socketType(), (*it).protocol());
01058 if (sockfd == -1)
01059 {
01060 setError(IO_ConnectError, errno);
01061 continue;
01062 }
01063 fcntl(sockfd, F_SETFD, FD_CLOEXEC);
01064 if (d->addressReusable)
01065 setAddressReusable(sockfd, true);
01066 setIPv6Only(d->ipv6only);
01067 cleanError();
01068 }
01069
01070
01071 d->status = created;
01072
01073
01074 if (doingtimeout && KSocks::self()->hasWorkingAsyncConnect())
01075 {
01076 fd_set rd, wr;
01077
01078 setBlockingMode(false);
01079
01080
01081 if (KSocks::self()->connect(sockfd, (*it).address(), (*it).length()) == -1)
01082 {
01083
01084 if (errno != EWOULDBLOCK && errno != EINPROGRESS)
01085 {
01086
01087 setError(IO_ConnectError, errno);
01088 ::close(sockfd);
01089 sockfd = -1;
01090 continue;
01091 }
01092
01093 FD_ZERO(&rd);
01094 FD_ZERO(&wr);
01095 FD_SET(sockfd, &rd);
01096 FD_SET(sockfd, &wr);
01097
01098 int retval = KSocks::self()->select(sockfd + 1, &rd, &wr, NULL, &d->timeout);
01099 if (retval == -1)
01100 {
01101 setError(IO_FatalError, errno);
01102 continue;
01103 }
01104 else if (retval == 0)
01105 {
01106 ::close(sockfd);
01107 sockfd = -1;
01108
01109
01110 d->status = lookupDone;
01111 setError(IO_TimeOutError, 0);
01112 return -3;
01113 }
01114
01115
01116 gettimeofday(&now, NULL);
01117 d->timeout.tv_sec = end.tv_sec - now.tv_sec;
01118 d->timeout.tv_usec = end.tv_usec - now.tv_usec;
01119 if (d->timeout.tv_usec < 0)
01120 {
01121 d->timeout.tv_usec += 1000*1000;
01122 d->timeout.tv_sec--;
01123 }
01124
01125
01126
01127
01128 int errcode;
01129 socklen_t len = sizeof(errcode);
01130 retval = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (char*)&errcode,
01131 &len);
01132 if (retval == -1 || errcode != 0)
01133 {
01134
01135
01136
01137 ::close(sockfd);
01138 sockfd = -1;
01139
01140
01141 if (d->timeout.tv_sec == 0 && d->timeout.tv_usec == 0)
01142 {
01143 d->status = lookupDone;
01144 setError(IO_TimeOutError, 0);
01145 return -3;
01146 }
01147
01148 setError(IO_ConnectError, errcode);
01149 continue;
01150 }
01151 }
01152
01153
01154
01155 setBlockingMode(true);
01156 d->status = connected;
01157 setFlags(IO_Sequential | IO_Raw | IO_ReadWrite | IO_Open | IO_Async);
01158 setBufferSize(d->flags & inputBufferedSocket ? -1 : 0,
01159 d->flags & outputBufferedSocket ? -1 : 0);
01160 emit connectionSuccess();
01161
01162 return 0;
01163 }
01164 else
01165 {
01166
01167 if (KSocks::self()->connect(sockfd, (*it).address(), (*it).length()) == -1)
01168 {
01169
01170
01171 setError(IO_ConnectError, errno);
01172 ::close(sockfd);
01173 sockfd = -1;
01174 continue;
01175 }
01176
01177 d->status = connected;
01178 setFlags(IO_Sequential | IO_Raw | IO_ReadWrite | IO_Open | IO_Async);
01179 setBufferSize(d->flags & inputBufferedSocket ? -1 : 0,
01180 d->flags & outputBufferedSocket ? -1 : 0);
01181 emit connectionSuccess();
01182
01183 return 0;
01184 }
01185 }
01186
01187
01188 emit connectionFailed(d->syserror);
01189
01190 return -1;
01191 }
01192
01193 int KExtendedSocket::startAsyncConnect()
01194 {
01195 cleanError();
01196
01197 if (d->status >= connected || d->flags & passiveSocket)
01198 return -2;
01199
01200 if (d->status == connecting)
01201
01202 return 0;
01203
01204
01205
01206
01207 if (d->status < lookupDone)
01208 {
01209 QObject::connect(this, SIGNAL(lookupFinished(int)), this, SLOT(startAsyncConnectSlot()));
01210 if (d->status < lookupInProgress)
01211 return startAsyncLookup();
01212 else
01213 return 0;
01214 }
01215
01216
01217
01218 d->status = connecting;
01219 QGuardedPtr<QObject> p = this;
01220 connectionEvent();
01221 if (!p)
01222 return -1;
01223 if (d->status < connecting)
01224 return -1;
01225 return 0;
01226 }
01227
01228 void KExtendedSocket::cancelAsyncConnect()
01229 {
01230 if (d->status != connecting)
01231 return;
01232
01233 if (sockfd != -1)
01234 {
01235
01236 if (d->qsnIn)
01237 delete d->qsnIn;
01238 if (d->qsnOut)
01239 delete d->qsnOut;
01240 d->qsnIn = d->qsnOut = NULL;
01241
01242 ::close(sockfd);
01243 sockfd = -1;
01244 }
01245 d->status = lookupDone;
01246 }
01247
01248 bool KExtendedSocket::open(int mode)
01249 {
01250 if (mode != IO_Raw | IO_ReadWrite)
01251 return false;
01252
01253 if (d->flags & passiveSocket)
01254 return listen() == 0;
01255 else if (d->status < connecting)
01256 return connect() == 0;
01257 else
01258 return false;
01259 }
01260
01261 void KExtendedSocket::close()
01262 {
01263 if (sockfd == -1 || d->status >= closing)
01264 return;
01265
01266
01267 if (d->flags & outputBufferedSocket && writeBufferSize() > 0)
01268 {
01269
01270 d->status = closing;
01271 if (d->qsnIn)
01272 delete d->qsnIn;
01273 d->qsnIn = NULL;
01274
01275
01276 }
01277 else
01278 {
01279
01280
01281 if (d->qsnIn)
01282 delete d->qsnIn;
01283 if (d->qsnOut)
01284 delete d->qsnOut;
01285 d->qsnIn = d->qsnOut = NULL;
01286
01287 ::close(sockfd);
01288 d->status = done;
01289 emit closed(readBufferSize() != 0 ? availRead : 0);
01290 }
01291
01292 }
01293
01294
01295 void KExtendedSocket::closeNow()
01296 {
01297 if (d->status >= done)
01298 return;
01299
01300
01301 delete d->qsnIn;
01302 delete d->qsnOut;
01303 d->qsnIn = d-&g