kdecore Library API Documentation

kextsock.cpp

00001 /* 00002 * This file is part of the KDE libraries 00003 * Copyright (C) 2000-2002 Thiago Macieira <thiagom@mail.com> 00004 * 00005 * $Id: kextsock.cpp,v 1.67.2.2 2004/03/01 13:18:40 waba Exp $ 00006 * 00007 * This library is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Library General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2 of the License, or (at your option) any later version. 00011 * 00012 * This library is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Library General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Library General Public License 00018 * along with this library; see the file COPYING.LIB. If not, write to 00019 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00020 * Boston, MA 02111-1307, USA. 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 // The system doesn't have sockaddr_in6 00062 // But we can tell netsupp.h to define it for us, according to the RFC 00063 #define CLOBBER_IN6 00064 #endif 00065 #include "netsupp.h" 00066 00067 #include "kextsocklookup.h" 00068 00069 // 00070 // Workarounds 00071 // 00072 00073 /* 00074 * getaddrinfo is defined in IEEE POSIX 1003.1g (Protocol Independent Interfaces) 00075 * and RFC 2553 (Basic Socket Interface for IPv6) extends that specification 00076 */ 00077 00078 #ifndef AI_NUMERICHOST 00079 /* Some systems have getaddrinfo according to POSIX, but not the RFC */ 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 // Internal class definitions 00096 // 00097 00098 class KExtendedSocketPrivate 00099 { 00100 public: 00101 int flags; // socket flags 00102 int status; // status 00103 int syserror; // the system error value 00104 00105 timeval timeout; // connection/acception timeout 00106 QString host; // requested hostname 00107 QString service; // requested service 00108 QString localhost; // requested bind host or local hostname 00109 QString localservice; // requested bind service or local port 00110 kde_addrinfo *resolution; // the resolved addresses 00111 kde_addrinfo *bindres; // binding resolution 00112 addrinfo *current; // used by asynchronous connection 00113 00114 KSocketAddress *local; // local socket address 00115 KSocketAddress *peer; // peer socket address 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 /* No flags given, use default */ 00141 00142 case KExtendedSocket::streamSocket: 00143 /* streaming socket requested */ 00144 hint.ai_socktype = SOCK_STREAM; 00145 break; 00146 00147 case KExtendedSocket::datagramSocket: 00148 /* datagram packet socket requested */ 00149 hint.ai_socktype = SOCK_DGRAM; 00150 break; 00151 00152 case KExtendedSocket::rawSocket: 00153 /* raw socket requested. I wouldn't do this if I were you... */ 00154 hint.ai_socktype = SOCK_RAW; 00155 break; 00156 00157 default: 00158 /* the flags were used in an invalid manner */ 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 /* check other flags */ 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; // user hasn't asked for Internet sockets 00186 if (flags & 0xf00 && (flags & 0x100) == 0) 00187 return false; // user hasn't asked for IPv4 sockets 00188 } 00189 #ifdef PF_INET6 00190 else if (p->ai_family == PF_INET6) 00191 { 00192 if (flags & 0x0e && (flags & 0x4) == 0) 00193 return false; // user hasn't asked for Internet sockets 00194 if (flags & 0xf00 && (flags & 0x200) == 0) 00195 return false; // user hasn't asked for IPv6 sockets 00196 } 00197 #endif 00198 else if (p->ai_family == PF_UNIX) 00199 { 00200 if (flags & 0x0e && (flags & 0x2) == 0) 00201 return false; // user hasn't asked for Unix Sockets 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; // not a known socket 00209 00210 // if we got here, the family is acceptable 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 // "skips" at most len bytes from file descriptor fd 00250 // that is, we will try and read that much data and discard 00251 // it. We will stop when we have read those or when the read 00252 // function returns error 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 // calls the correct deallocation routine 00275 // also uses by-reference parameter to simplify caller routines, because 00276 // we set the parameter to NULL after deallocation 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 * class KExtendedSocketLookup (internal use) 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; // no service; error? 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; // No data? Bizarre, but nonetheless possible 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 * class KExtendedSocket 00414 */ 00415 00416 // default constructor 00417 KExtendedSocket::KExtendedSocket() : 00418 sockfd(-1), d(new KExtendedSocketPrivate) 00419 { 00420 } 00421 00422 // constructor with hostname 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 // same 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 // destroy the class 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 * Sets socket flags 00491 * This is only allowed if we are in nothing state 00492 */ 00493 int KExtendedSocket::setSocketFlags(int flags) 00494 { 00495 if (d->status > nothing) 00496 return -1; // error! 00497 00498 return d->flags = flags; 00499 } 00500 00501 int KExtendedSocket::socketFlags() const 00502 { 00503 return d->flags; 00504 } 00505 00506 /* 00507 * Sets socket target hostname 00508 * This is only allowed if we are in nothing state 00509 */ 00510 bool KExtendedSocket::setHost(const QString& host) 00511 { 00512 if (d->status > nothing) 00513 return false; // error! 00514 00515 d->host = host; 00516 return true; 00517 } 00518 00519 /* 00520 * returns the hostname 00521 */ 00522 QString KExtendedSocket::host() const 00523 { 00524 return d->host; 00525 } 00526 00527 /* 00528 * Sets the socket target port/service 00529 * Same thing: only state 'nothing' 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; // error 00540 00541 d->service = service; 00542 return true; 00543 } 00544 00545 /* 00546 * returns the service port number 00547 */ 00548 QString KExtendedSocket::port() const 00549 { 00550 return d->service; 00551 } 00552 00553 /* 00554 * sets the address 00555 */ 00556 bool KExtendedSocket::setAddress(const QString& host, int port) 00557 { 00558 return setHost(host) && setPort(port); 00559 } 00560 00561 /* 00562 * the same 00563 */ 00564 bool KExtendedSocket::setAddress(const QString& host, const QString& serv) 00565 { 00566 return setHost(host) && setPort(serv); 00567 } 00568 00569 /* 00570 * Sets the bind hostname 00571 * This is only valid in the 'nothing' state and if this is not a 00572 * passiveSocket socket 00573 */ 00574 bool KExtendedSocket::setBindHost(const QString& host) 00575 { 00576 if (d->status > nothing || d->flags & passiveSocket) 00577 return false; // error 00578 00579 d->localhost = host; 00580 return true; 00581 } 00582 00583 /* 00584 * Unsets the bind hostname 00585 * same thing 00586 */ 00587 bool KExtendedSocket::unsetBindHost() 00588 { 00589 if (d->status > nothing || d->flags & passiveSocket) 00590 return false; // error 00591 00592 d->localhost.truncate(0); 00593 return true; 00594 } 00595 00596 /* 00597 * returns the binding host 00598 */ 00599 QString KExtendedSocket::bindHost() const 00600 { 00601 return d->localhost; 00602 } 00603 00604 /* 00605 * Sets the bind port 00606 * Same condition as setBindHost 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; // error 00617 00618 d->localservice = service; 00619 return true; 00620 } 00621 00622 /* 00623 * unsets the bind port 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 * returns the binding port 00636 */ 00637 QString KExtendedSocket::bindPort() const 00638 { 00639 return d->localservice; 00640 } 00641 00642 /* 00643 * sets the binding address 00644 */ 00645 bool KExtendedSocket::setBindAddress(const QString& host, int port) 00646 { 00647 return setBindHost(host) && setBindPort(port); 00648 } 00649 00650 /* 00651 * same 00652 */ 00653 bool KExtendedSocket::setBindAddress(const QString& host, const QString& service) 00654 { 00655 return setBindHost(host) && setBindPort(service); 00656 } 00657 00658 /* 00659 * unsets binding address 00660 */ 00661 bool KExtendedSocket::unsetBindAddress() 00662 { 00663 return unsetBindHost() && unsetBindPort(); 00664 } 00665 00666 /* 00667 * sets the timeout for the connection 00668 */ 00669 bool KExtendedSocket::setTimeout(int secs, int usecs) 00670 { 00671 if (d->status >= connected) // closed? 00672 return false; 00673 00674 d->timeout.tv_sec = secs; 00675 d->timeout.tv_usec = usecs; 00676 return true; 00677 } 00678 00679 /* 00680 * returns the timeout 00681 */ 00682 timeval KExtendedSocket::timeout() const 00683 { 00684 return d->timeout; 00685 } 00686 00687 /* 00688 * Sets the blocking mode on this socket 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; // error! 00698 00699 int fdflags = fcntl(sockfd, F_GETFL, 0); 00700 if (fdflags == -1) 00701 return false; // error! 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 * Returns the blocking mode on the socket 00718 */ 00719 bool KExtendedSocket::blockingMode() 00720 { 00721 cleanError(); 00722 if (d->status < created) 00723 return false; // sockets not created are in blocking mode 00724 00725 if (sockfd == -1) 00726 return false; // error 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; // non-blocking == false 00735 } 00736 00737 /* 00738 * Sets the reusability flag for this socket in the OS 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; // just to be on the safe side 00764 00765 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof(on)) == -1) 00766 return false; 00767 return true; 00768 } 00769 00770 /* 00771 * Retrieves the reusability flag for this socket 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 * Set the IPV6_V6ONLY flag 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; // can't set on a non-existing socket 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 // we don't have the IPV6_V6ONLY constant in this system 00818 d->ipv6only = enable; 00819 00820 setError(IO_UnspecifiedError, ENOSYS); 00821 return false; // can't set if we don't know about this flag 00822 #endif 00823 } 00824 00825 /* 00826 * retrieve the IPV6_V6ONLY flag 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 // we don't have the constant 00849 setError(IO_UnspecifiedError, ENOSYS); 00850 return false; 00851 #endif 00852 } 00853 00854 /* 00855 * Sets the buffer sizes in this socket 00856 * Also, we create or delete the socket notifiers 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; // no I/O on passive sockets 00869 00870 if (rsize < -2) 00871 return false; 00872 00873 if (wsize < -2) 00874 return false; 00875 00876 // LOCK BUFFER MUTEX 00877 00878 // The input socket notifier is always enabled 00879 // That happens because we want to be notified of when the socket gets 00880 // closed 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 // user wants to disable input buffering 00891 d->flags &= ~inputBufferedSocket; 00892 00893 consumeReadBuffer(readBufferSize(), NULL, true); 00894 d->inMaxSize = 0; 00895 } 00896 else if (rsize != -2) 00897 { 00898 // enabling input buffering 00899 if (rsize) 00900 d->flags |= inputBufferedSocket; 00901 d->inMaxSize = rsize; 00902 00903 if (rsize > 0 && (unsigned)rsize < readBufferSize()) 00904 // input buffer has more data than the new size; discard 00905 consumeReadBuffer(readBufferSize() - rsize, NULL, true); 00906 00907 } 00908 00909 if (wsize == 0 && d->flags & outputBufferedSocket) 00910 { 00911 // disabling output buffering 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 // enabling input buffering 00921 if (wsize) 00922 d->flags |= outputBufferedSocket; 00923 d->outMaxSize = wsize; 00924 00925 if (wsize > 0 && (unsigned)wsize < writeBufferSize()) 00926 // output buffer is bigger than it is to become; shrink 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 // if the class is being created now, there's nothing to write yet 00934 // so socketActivityWrite() will get called once and disable 00935 // the notifier 00936 } 00937 } 00938 00939 // UNLOCK BUFFER MUTEX 00940 00941 setFlags((mode() & ~IO_Raw) | ((d->flags & bufferedSocket) ? 0 : IO_Raw)); 00942 00943 // check we didn't turn something off we shouldn't 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 * Finds the local address for this socket 00955 * if we have done this already, we return it. Otherwise, we'll have 00956 * to find the socket name 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 * Same thing, but for peer address. Which means this does not work on 00970 * passiveSocket and that we require to be connected already. Also note that 00971 * the behavior on connectionless sockets is not defined here. 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 * Perform the lookup on the addresses given 00985 */ 00986 int KExtendedSocket::lookup() 00987 { 00988 cleanError(); 00989 if (d->status >= lookupInProgress) 00990 return EAI_BADFLAGS; // we needed an error... 00991 00992 addrinfo hint; 00993 00994 memset(&hint, 0, sizeof(hint)); 00995 hint.ai_family = AF_UNSPEC; 00996 00997 // perform the global lookup before 00998 if (d->resolution == NULL) 00999 { 01000 /* check socket type flags */ 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 /* leave hint.ai_socktype the same */ 01015 hint.ai_flags |= AI_PASSIVE; // this is passive, for bind() 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 * Performs an asynchronous lookup on the given address(es) 01031 */ 01032 int KExtendedSocket::startAsyncLookup() 01033 { 01034 cleanError(); 01035 if (d->status > lookupInProgress) 01036 return -1; 01037 if (d->status == lookupInProgress) 01038 // already in progress 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; // number of asynchronous lookups 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 // damn! Early error in the lookup 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 // if we are here, there were no errors 01095 if (n) 01096 d->status = lookupInProgress; // only if there actually is a running lookup 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; // what's to cancel? 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; // error! 01136 if (!d->resolution) return -2; 01137 01138 addrinfo *p; 01139 01140 // doing the loop: 01141 for (p = d->resolution->data; p; p = p->ai_next) 01142 { 01143 // check for family restriction 01144 if (!valid_family(p, d->flags)) 01145 continue; 01146 01147 //kdDebug(170) << "Trying to listen on " << pretty_sock(p) << endl; 01148 sockfd = ::socket(p->ai_family, p->ai_socktype, p->ai_protocol); 01149 if (sockfd == -1) 01150 { 01151 // socket failed creating 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 // ok, socket has bound 01171 // kdDebug(170) << "Socket bound: " << sockfd << endl; 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; // error! 01208 01209 // let's see 01210 // if we have a timeout in place, we have to place this socket in non-blocking 01211 // mode 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); // turn on non-blocking 01222 FD_ZERO(&set); 01223 FD_SET(sockfd, &set); 01224 01225 //kdDebug(170).form("Accepting on %d with %d.%06d second timeout\n", 01226 // sockfd, d->timeout.tv_sec, d->timeout.tv_usec); 01227 // check if there is anything to accept now 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; // system error 01233 } 01234 else if (retval == 0 || !FD_ISSET(sockfd, &set)) 01235 { 01236 setError(IO_TimeOutError, 0); 01237 return -3; // timeout 01238 } 01239 } 01240 01241 // it's common stuff here 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 //kdDebug(170).form("Socket %d accepted socket %d\n", sockfd, newfd); 01255 01256 setBlockingMode(block); // restore blocking mode 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); // always unbuffered here. User can change that later 01263 01264 return 0; 01265 } 01266 01267 /* 01268 * tries to connect 01269 * 01270 * FIXME! 01271 * This function is critical path. It has to be cleaned up and made faster 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 // Ok, things are a little tricky here 01286 // Let me explain 01287 // getaddrinfo() will return several different families of sockets 01288 // When we have to bind before we connect, we have to make sure we're binding 01289 // and connecting to the same family, or things won't work 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 // kdDebug(170).form("Connection with timeout of %d.%06d seconds (ends in %d.%06d)\n", 01303 // d->timeout.tv_sec, d->timeout.tv_usec, end.tv_sec, end.tv_usec); 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 // check for family restriction 01313 if (!valid_family(p, d->flags)) 01314 continue; 01315 01316 // kdDebug(170) << "Trying to connect to " << pretty_sock(p) << endl; 01317 if (q != NULL) 01318 { 01319 // kdDebug(170) << "Searching bind socket for family " << p->ai_family << endl; 01320 if (q->ai_family != p->ai_family) 01321 // differing families, scan bindres for a matching family 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 // no matching families for this 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; // cannot create this socket 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 // no need to bind, just create 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 // kdDebug(170) << "Socket " << sockfd << " created" << endl; 01370 d->status = created; 01371 01372 // check if we have to do timeout 01373 if (doingtimeout && KSocks::self()->hasWorkingAsyncConnect()) 01374 { 01375 fd_set rd, wr; 01376 01377 setBlockingMode(false); 01378 01379 // now try and connect 01380 if (KSocks::self()->connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) 01381 { 01382 // this could be EWOULDBLOCK 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; // nope, another error 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; // system error 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; // time out 01412 } 01413 01414 // adjust remaining time 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 // kdDebug(170).form("Socket %d activity; %d.%06d seconds remaining\n", 01424 // sockfd, d->timeout.tv_sec, d->timeout.tv_usec); 01425 01426 // this means that an event occurred in the socket 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 // socket did not connect 01434 kdDebug(170) << "Socket " << sockfd << " did not connect: " 01435 << strerror(errcode) << endl; 01436 ::close(sockfd); 01437 sockfd = -1; 01438 01439 // this is HIGHLY UNLIKELY 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; // time out 01445 } 01446 01447 setError(IO_ConnectError, errcode); 01448 continue; 01449 } 01450 } 01451 01452 // getting here means it connected 01453 // setBufferSize() takes care of creating the socket notifiers 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 // kdDebug(170) << "Socket " << sockfd << " connected\n"; 01461 return 0; 01462 } 01463 else 01464 { 01465 // without timeouts 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 // kdDebug(170) << "Socket " << sockfd << " connected\n"; 01481 return 0; // it connected 01482 } 01483 } 01484 01485 // getting here means no socket connected or stuff like that 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 // check status 01495 if (d->status >= connected || d->flags & passiveSocket) 01496 return -2; 01497 01498 if (d->status == connecting) 01499 // already on async connect 01500 return 0; 01501 01502 // check if we have to do lookup 01503 // if we do, then we'll use asynchronous lookup and use 01504 // signal lookupFinished to do connection 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; // we still have to wait 01512 } 01513 01514 // here we have d->status >= lookupDone and <= connecting 01515 // we can do our connection 01516 d->status = connecting; 01517 QGuardedPtr<QObject> p = this; 01518 connectionEvent(); 01519 if (!p) 01520 return -1; // We have been deleted. 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 // we have a waiting connection 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; // invalid open mode 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; // nothing to close 01563 01564 // LOCK BUFFER MUTEX 01565 if (d->flags & outputBufferedSocket && writeBufferSize() > 0) 01566 { 01567 // write buffer not empty, go into closing state 01568 d->status = closing; 01569 if (d->qsnIn) 01570 delete d->qsnIn; 01571 d->qsnIn = NULL; 01572 // we keep the outgoing socket notifier because we want 01573 // to send data, but not receive 01574 } 01575 else 01576 { 01577 // nope, write buffer is empty 01578 // we can close now 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 // UNLOCK BUFFER MUTEX 01590 } 01591 01592 01593 void KExtendedSocket::closeNow() 01594 { 01595 if (d->status >= done) 01596 return; // nothing to close 01597 01598 // close the socket 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 // release our hold on the socket 01623 sockfd = -1; 01624 d->status = done; 01625 01626 // also do some garbage collecting 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 // now that the socket notificators are done with, we can flush out the buffers 01647 consumeReadBuffer(readBufferSize(), NULL, true); 01648 consumeWriteBuffer(writeBufferSize()); 01649 01650 // don't delete d 01651 // leave that for the destructor 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; // nothing to do 01665 01666 // LOCK MUTEX 01667 01668 unsigned written = 0; 01669 unsigned offset = outBufIndex; // this happens only for the first 01670 while (writeBufferSize() - written > 0) 01671 { 01672 // we have to write each output buffer in outBuf 01673 // but since we can have several very small buffers, we can make things 01674 // better by concatenating a few of them into a big buffer 01675 // question is: how big should that buffer be? 16 kB should be enough 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 // now try to write those bytes 01690 int wrote = KSocks::self()->write(sockfd, buf, count); 01691 01692 if (wrote == -1) 01693 { 01694 // could be EAGAIN (EWOULDBLOCK) 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 // UNLOCK MUTEX 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 // we aren't buffering this socket, so just pass along 01724 // the call to the real read method 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 // this socket is being buffered. So read from the buffer 01738 01739 // LOCK BUFFER MUTEX 01740 01741 retval = consumeReadBuffer(maxlen, data); 01742 if (retval == 0) 01743 { 01744 // consumeReadBuffer returns 0 only if the buffer is 01745 // empty 01746 if (sockfd == -1) 01747 return 0; // buffer is clear now, indicate EOF 01748 setError(IO_ReadError, EWOULDBLOCK); 01749 retval = -1; 01750 } 01751 01752 // UNLOCK BUFFER MUTEX 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; // what's to write? 01768 01769 int retval; 01770 01771 if ((d->flags & outputBufferedSocket) == 0) 01772 { 01773 // socket not buffered. Just call write 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 // socket is buffered. Feed the write buffer 01783 01784 // LOCK BUFFER MUTEX 01785 01786 register unsigned wsize = writeBufferSize(); 01787 if (d->outMaxSize == (int)wsize) // (int) to get rid of annoying warning 01788 { 01789 // buffer is full! 01790 setError(IO_WriteError, EWOULDBLOCK); 01791 retval = -1; 01792 } 01793 else 01794 { 01795 if (d->outMaxSize != -1 && wsize + len > (unsigned)d->outMaxSize) 01796 // we cannot write all data. Write just as much as to fill the buffer 01797 len = d->outMaxSize - wsize; 01798 01799 // len > 0 here 01800 retval = feedWriteBuffer(len, data); 01801 if (wsize == 0 || d->emitWrite) 01802 // buffer was empty, which means that the notifier is probably disabled 01803 d->qsnOut->setEnabled(true); 01804 } 01805 01806 // UNLOCK BUFFER MUTEX 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 // need to LOCK MUTEX around this call... 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 // Always return -1, indicating this is not supported 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 // as of now, we don't do any extra processing 01840 // we only work in input-buffered sockets 01841 if (d->flags & inputBufferedSocket) 01842 return KBufferedIO::bytesAvailable(); 01843 01844 return 0; // TODO: FIONREAD ioctl 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(); // do read processing 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 // Please read the comments before kde_getaddrinfo in netsupp.cpp 01903 // for the reason we're using it 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 // A loookup error occurred and nothing was resolved 01910 // However, since the user could have just dialed up to the ISP 01911 // and new nameservers were written to /etc/resolv.conf, we have 01912 // to re-parse that 01913 res_init(); 01914 01915 // Now try looking up again 01916 err = kde_getaddrinfo(_host, _serv, &hint, res); 01917 } 01918 #endif 01919 01920 return err; 01921 } 01922 01923 // sets the emission of the readyRead signal 01924 void KExtendedSocket::enableRead(bool enable) 01925 { 01926 // check if we can disable the socket notifier 01927 // saves us a few cycles 01928 // this is so because in buffering mode, we rely on these signals 01929 // being emitted to do our I/O. We couldn't disable them here 01930 if (!enable && (d->flags & inputBufferedSocket) == 0 && d->qsnIn) 01931 d->qsnIn->setEnabled(false); 01932 else if (enable && d->qsnIn) 01933 // we can enable it always 01934 d->qsnIn->setEnabled(true); 01935 d->emitRead = enable; 01936 } 01937 01938 // sets the emission of the readyWrite signal 01939 void KExtendedSocket::enableWrite(bool enable) 01940 { 01941 // same thing as above 01942 if (!enable && (d->flags & outputBufferedSocket) == 0 && d->qsnOut) 01943 d->qsnOut->setEnabled(false); 01944 else if (enable && d->qsnOut) 01945 // we can enable it always 01946 d->qsnOut->setEnabled(true); 01947 d->emitWrite = enable; 01948 } 01949 01950 // protected slot 01951 // this is connected to d->qsnIn::activated(int) 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 // do we need to do I/O here? 01968 if (d->flags & inputBufferedSocket) 01969 { 01970 // aye. Do read from the socket and feed our buffer 01971 QByteArray a; 01972 char buf[1024]; 01973 int len, totalread = 0; 01974 01975 // LOCK MUTEX 01976 01977 unsigned cursize = readBufferSize(); 01978 01979 if (d->inMaxSize == -1 || cursize < (unsigned)d->inMaxSize) 01980 { 01981 do 01982 { 01983 // check that we can read that many bytes 01984 if (d->inMaxSize != -1 && d->inMaxSize - (cursize + totalread) < sizeof(buf)) 01985 // no, that would overrun the buffer 01986 // note that this will also make us exit the loop 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 // normal read operation 01995 a.resize(a.size() + len); 01996 memcpy(a.data() + totalread, buf, len); 01997 totalread += len; // totalread == a.size() now 01998 } 01999 else if (len == 0) 02000 { 02001 // EOF condition here 02002 ::close(sockfd); 02003 sockfd = -1; // we're closed 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 // error! 02016 setError(IO_ReadError, errno); 02017 return; 02018 } 02019 // will loop only for normal read operations 02020 } 02021 while (len == sizeof(buf)); 02022 02023 feedReadBuffer(a.size(), a.data()); 02024 } 02025 02026 // UNLOCK MUTEX 02027 } 02028 else 02029 { 02030 // No input buffering, but the notifier fired 02031 // That means that either there is data to be read or that the 02032 // socket closed. 02033 02034 // try to read one byte. If we can't, then the socket got closed 02035 02036 char c; 02037 int len = KSocks::self()->recv(sockfd, &c, sizeof(c), MSG_PEEK); 02038 if (len == 0) 02039 { 02040 // yes, it's an EOF condition 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 // check if we can disable the notifier 02075 d->qsnOut->setEnabled(!empty); // leave it enabled only if we have more data to send 02076 } 02077 if (d->status == closing && empty) 02078 { 02079 // done sending the missing data! 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 // this function is called whenever we have a "connection event" 02092 // that is, whenever our asynchronously connecting socket throws 02093 // an event 02094 void KExtendedSocket::connectionEvent() 02095 { 02096 if (d->status != connecting) 02097 return; // move along. There's nothing to see here 02098 if (d->resolution == 0 || d->resolution->data == 0) 02099 { 02100 // We have a problem! Abort? 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 // our socket has activity 02110 // find out what it was 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 // socket activity and there was error? 02118 // that means the socket probably did not connect 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 // hmm, socket activity and there was no error? 02132 // that means it connected 02133 // YAY! 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 // ok, we have to try something here 02146 // and sockfd == -1 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 // same code as in connect() 02157 if (q != NULL) 02158 { 02159 if (q->ai_family != d->current->ai_family) 02160 // differing families, scan bindres for a matching family 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 // no matching families for this 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; // cannot create this socket 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 // no need to bind, just create 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 // error here is either EWOULDBLOCK or EINPROGRESS 02221 // so, it is a good condition 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 // ok, let the Qt event loop do the selecting for us 02228 // just make sure we know where to go on in the next iteration 02229 d->current = p; 02230 return; 02231 } 02232 02233 // eh, what? 02234 // the non-blocking socket returned valid connection? 02235 // already? 02236 // I suppose that could happen... 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 // if we got here, it means that there are no more options to connect 02248 d->status = lookupDone; // go back 02249 emit connectionFailed(errcode); 02250 } 02251 02252 void KExtendedSocket::dnsResultsReady() 02253 { 02254 // check that this function was called in a valid state 02255 if (d->status != lookupInProgress) 02256 return; 02257 02258 // valid state. Are results fully ready? 02259 if ((d->dns != NULL && d->dns->isWorking()) || 02260 (d->dnsLocal != NULL && d->dnsLocal->isWorking())) 02261 // no, still waiting for answer in one of the lookups 02262 return; 02263 02264 // ok, we have all results 02265 // count how many results we have 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 // kdDebug(170) << "Performing lookup on " << host << "|" << port << endl; 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 // kdDebug(170) << "Using socket " << pretty_sock(p) << endl; 02359 l.append(ai); 02360 } 02361 02362 if ( error ) 02363 *error = 0; // all is fine! 02364 02365 kde_freeaddrinfo(res); // this one we know where it came from 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 /* find out the socket length, in advance 02376 * we use a sockaddr allocated on the heap just not to pass down 02377 * a NULL pointer to the first call. Some systems are reported to 02378 * set len to 0 if we pass NULL as the sockaddr */ 02379 if (KSocks::self()->getsockname(fd, sa, &len) == -1) 02380 return NULL; // error! 02381 02382 /* was it enough? */ 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 /* nope, malloc a new socket with the proper size */ 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; // out of memory 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 /* This is exactly the same code as localAddress, except 02416 * we call getpeername here */ 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 /* find out the socket length, in advance 02424 * we use a sockaddr allocated on the heap just not to pass down 02425 * a NULL pointer to the first call. Some systems are reported to 02426 * set len to 0 if we pass NULL as the sockaddr */ 02427 if (KSocks::self()->getpeername(fd, sa, &len) == -1) 02428 return NULL; // error! 02429 02430 /* was it enough? */ 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 /* nope, malloc a new socket with the proper size */ 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; // out of memory 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 * class KAddressInfo 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"
KDE Logo
This file is part of the documentation for kdecore Library Version 3.2.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Mar 16 17:21:41 2005 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003