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