• Skip to content
  • Skip to link menu
KDE 4.3 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KDECore

k3socketdevice.cpp

Go to the documentation of this file.
00001 /*  -*- C++ -*-
00002  *  Copyright (C) 2003,2005 Thiago Macieira <thiago@kde.org>
00003  *
00004  *
00005  *  Permission is hereby granted, free of charge, to any person obtaining
00006  *  a copy of this software and associated documentation files (the
00007  *  "Software"), to deal in the Software without restriction, including
00008  *  without limitation the rights to use, copy, modify, merge, publish,
00009  *  distribute, sublicense, and/or sell copies of the Software, and to
00010  *  permit persons to whom the Software is furnished to do so, subject to
00011  *  the following conditions:
00012  *
00013  *  The above copyright notice and this permission notice shall be included
00014  *  in all copies or substantial portions of the Software.
00015  *
00016  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00017  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00018  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00019  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00020  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00021  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00022  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00023  */
00024 
00025 // syssocket.h needs to come before any header that includes k3socketbase.h
00026 #include "syssocket.h"
00027 
00028 #include "k3socketdevice.h" //krazy:exclude=includes (KDE3 compat: not worth fixing)
00029 
00030 #include <config.h>
00031 #include <config-network.h>
00032 
00033 #include <QMap>
00034 
00035 #ifdef HAVE_SYS_FILIO_H
00036 # include <sys/filio.h>
00037 #endif
00038 #include <sys/types.h>
00039 #include <sys/socket.h>
00040 #include <sys/time.h>
00041 #include <sys/ioctl.h>
00042 #include <errno.h>
00043 #include <fcntl.h>
00044 #include <netinet/in.h>
00045 #include <netinet/tcp.h>    // WARNING: verify if this is portable
00046 #include <unistd.h>
00047 
00048 #ifdef HAVE_POLL
00049 # include <sys/poll.h>
00050 #else
00051 # ifdef HAVE_SYS_SELECT_H
00052 #  include <sys/select.h>
00053 # endif
00054 #endif
00055 
00056 #ifdef Q_WS_WIN
00057 #include <windows.h>
00058 #endif
00059 
00060 #include <QMutex>
00061 #include <QSocketNotifier>
00062 
00063 #include "k3resolver.h"
00064 #include "k3socketaddress.h"
00065 #include "k3socketbase.h"
00066 #ifndef KDE_USE_FINAL
00067 #include "k3socks.h"
00068 #endif
00069 using namespace KNetwork;
00070 
00071 class KNetwork::KSocketDevicePrivate
00072 {
00073 public:
00074   mutable QSocketNotifier *input, *output, *exception;
00075   KSocketAddress local, peer;
00076   int af;
00077   int proto;
00078 
00079   inline KSocketDevicePrivate()
00080   {
00081     input = output = exception = 0L;
00082     af = proto = 0;
00083   }
00084 };
00085 
00086 
00087 KSocketDevice::KSocketDevice(const KSocketBase* parent, QObject* objparent)
00088   : KActiveSocketBase(objparent), m_sockfd(-1),
00089     d(new KSocketDevicePrivate)
00090 {
00091   setSocketDevice(this);
00092   if (parent)
00093     setSocketOptions(parent->socketOptions());
00094 }
00095 
00096 KSocketDevice::KSocketDevice(int fd, OpenMode mode)
00097   : KActiveSocketBase(0L), m_sockfd(fd), d(new KSocketDevicePrivate)
00098 {
00099   if (mode)
00100     mode |= Unbuffered;
00101   KActiveSocketBase::open(mode);
00102   setSocketDevice(this);
00103   d->af = localAddress().family();
00104 }
00105 
00106 KSocketDevice::KSocketDevice(QObject* parent)
00107   : KActiveSocketBase(parent), m_sockfd(-1), d(new KSocketDevicePrivate)
00108 {
00109   setSocketDevice(this);
00110 }
00111 
00112 KSocketDevice::KSocketDevice(bool, const KSocketBase* parent)
00113   : KActiveSocketBase(0L), m_sockfd(-1), d(new KSocketDevicePrivate)
00114 {
00115   // do not set parent
00116   if (parent)
00117     setSocketOptions(parent->socketOptions());
00118 }
00119 
00120 KSocketDevice::~KSocketDevice()
00121 {
00122   close();          // deletes the notifiers
00123   unsetSocketDevice();      // prevent double deletion
00124   delete d;
00125 }
00126 
00127 int KSocketDevice::socket() const
00128 {
00129     return m_sockfd;
00130 }
00131 
00132 int KSocketDevice::capabilities() const
00133 {
00134     return 0;
00135 }
00136 
00137 bool KSocketDevice::setSocketOptions(int opts)
00138 {
00139   // must call parent
00140   QMutexLocker locker(mutex());
00141   KSocketBase::setSocketOptions(opts);
00142 
00143   if (m_sockfd == -1)
00144     return true;        // flags are stored
00145 
00146 #ifdef Q_WS_WIN
00147   u_long iMode = ((opts & Blocking) == Blocking) ? 0 : 1;
00148   // disable non blocking
00149   if (ioctlsocket(m_sockfd, FIONBIO, &iMode) == SOCKET_ERROR)
00150   {
00151     // socket can't made blocking because WSAAsyncSelect/WSAEventSelect (==QSocketNotifier)
00152     // is activated for them
00153     if(WSAGetLastError() == WSAEINVAL)
00154       return true;
00155     qDebug("socket set %s failed %d", iMode ? "nonblocking" : "blocking", GetLastError());
00156     setError(UnknownError);
00157     return false;  // error
00158   }
00159 
00160 #else
00161     {
00162       int fdflags = fcntl(m_sockfd, F_GETFL, 0);
00163       if (fdflags == -1)
00164     {
00165       setError(UnknownError);
00166       return false;     // error
00167     }
00168 
00169       if (opts & Blocking)
00170     fdflags &= ~O_NONBLOCK;
00171       else
00172     fdflags |= O_NONBLOCK;
00173 
00174       if (fcntl(m_sockfd, F_SETFL, fdflags) == -1)
00175     {
00176       setError(UnknownError);
00177       return false;     // error
00178     }
00179     }
00180 #endif
00181 
00182     {
00183       int on = opts & AddressReuseable ? 1 : 0;
00184       if (setsockopt(m_sockfd, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof(on)) == -1)
00185     {
00186       setError(UnknownError);
00187       return false;     // error
00188     }
00189     }
00190 
00191 #if defined(IPV6_V6ONLY) && defined(AF_INET6)
00192   if (d->af == AF_INET6)
00193     {
00194       // don't try this on non-IPv6 sockets, or we'll get an error
00195 
00196       int on = opts & IPv6Only ? 1 : 0;
00197       if (setsockopt(m_sockfd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&on, sizeof(on)) == -1)
00198     {
00199       setError(UnknownError);
00200       return false;     // error
00201     }
00202     }
00203 #endif
00204 
00205    {
00206      int on = opts & Broadcast ? 1 : 0;
00207      if (setsockopt(m_sockfd, SOL_SOCKET, SO_BROADCAST, (char*)&on, sizeof(on)) == -1)
00208        {
00209      setError(UnknownError);
00210      return false;      // error
00211        }
00212    }
00213 
00214   if ((d->proto == IPPROTO_TCP || d->proto == 0) &&
00215       (d->af == AF_INET
00216 #if defined(AF_INET6)
00217        || d->af == AF_INET6
00218 #endif
00219        ))
00220    {
00221      int on = opts & NoDelay ? 1 : 0;
00222      if (setsockopt(m_sockfd, IPPROTO_TCP, TCP_NODELAY, (char*)&on, sizeof(on)) == -1)
00223        {
00224      setError(UnknownError);
00225      return false;      // error
00226        }
00227    }
00228 
00229   return true;          // all went well
00230 }
00231 
00232 void KSocketDevice::close()
00233 {
00234   resetError();
00235   if (m_sockfd != -1)
00236     {
00237       delete d->input;
00238       delete d->output;
00239       delete d->exception;
00240 
00241       d->input = d->output = d->exception = 0L;
00242 #ifdef Q_WS_WIN
00243       ::closesocket(m_sockfd);
00244 #else
00245       d->local.setFamily(AF_UNSPEC);
00246       d->peer.setFamily(AF_UNSPEC);
00247 
00248       ::close(m_sockfd);
00249 #endif
00250     }
00251   setOpenMode(0);       // closed
00252 
00253   m_sockfd = -1;
00254 }
00255 
00256 bool KSocketDevice::flush()
00257 {
00258     return false;
00259 }
00260 
00261 bool KSocketDevice::create(int family, int type, int protocol)
00262 {
00263   resetError();
00264 
00265   if (m_sockfd != -1)
00266     {
00267       // it's already created!
00268       setError(AlreadyCreated);
00269       return false;
00270     }
00271 
00272   // no socket yet; we have to create it
00273   m_sockfd = kde_socket(family, type, protocol);
00274 
00275   if (m_sockfd == -1)
00276     {
00277       setError(NotSupported);
00278       return false;
00279     }
00280 
00281   d->af = family;
00282   d->proto = protocol;
00283   setSocketOptions(socketOptions());
00284   setOpenMode(Unbuffered);  // there's no "Open" flag
00285   return true;      // successfully created
00286 }
00287 
00288 bool KSocketDevice::create(const KResolverEntry& address)
00289 {
00290   return create(address.family(), address.socketType(), address.protocol());
00291 }
00292 
00293 bool KSocketDevice::bind(const KResolverEntry& address)
00294 {
00295   resetError();
00296 
00297   if (m_sockfd == -1 && !create(address))
00298     return false;       // failed creating
00299 
00300   // we have a socket, so try and bind
00301   if (kde_bind(m_sockfd, address.address(), address.length()) == -1)
00302     {
00303       if (errno == EADDRINUSE)
00304       {
00305     setError(AddressInUse);
00306     return false;
00307       }
00308       else if (errno == EINVAL)
00309     setError(AlreadyBound);
00310       else 
00311        {
00312 #ifdef Q_WS_WIN
00313          qDebug(" bind failed: %s ",address.address().toString().toLatin1().constData());
00314 #endif
00315          // assume the address is the cause
00316          setError(NotSupported);
00317          return false;
00318        } 
00319     }
00320 
00321   return true;
00322 }
00323 
00324 bool KSocketDevice::listen(int backlog)
00325 {
00326   if (m_sockfd != -1)
00327     {
00328       if (kde_listen(m_sockfd, backlog) == -1)
00329     {
00330       setError(NotSupported);
00331       return false;
00332     }
00333 
00334       resetError();
00335       setOpenMode(QIODevice::Unbuffered | QIODevice::ReadWrite);
00336       return true;
00337     }
00338 
00339   // we don't have a socket
00340   // can't listen
00341   setError(NotCreated);
00342   return false;
00343 }
00344 
00345 bool KSocketDevice::connect(const KResolverEntry& address, OpenMode mode)
00346 {
00347   resetError();
00348 
00349   if (m_sockfd == -1 && !create(address))
00350     return false;       // failed creating!
00351 
00352   if (kde_connect(m_sockfd, address.address(), address.length()) == -1)
00353     {
00354       if (errno == EISCONN)
00355     {
00356       KActiveSocketBase::open(Unbuffered | mode);
00357       return true;      // we're already connected
00358     }
00359       else if (errno == EALREADY || errno == EINPROGRESS)
00360     {
00361       KActiveSocketBase::open(Unbuffered | mode);
00362       setError(InProgress);
00363       return true;
00364     }
00365       else if (errno == ECONNREFUSED)
00366     setError(ConnectionRefused);
00367       else if (errno == ENETDOWN || errno == ENETUNREACH ||
00368            errno == ENETRESET || errno == ECONNABORTED ||
00369            errno == ECONNRESET || errno == EHOSTDOWN ||
00370            errno == EHOSTUNREACH)
00371     setError(NetFailure);
00372       else
00373     setError(NotSupported);
00374 
00375       return false;
00376     }
00377 
00378   KActiveSocketBase::open(Unbuffered | mode);
00379   return true;          // all is well
00380 }
00381 
00382 KSocketDevice* KSocketDevice::accept()
00383 {
00384   if (m_sockfd == -1)
00385     {
00386       // can't accept without a socket
00387       setError(NotCreated);
00388       return 0L;
00389     }
00390 
00391   struct sockaddr sa;
00392   socklen_t len = sizeof(sa);
00393   int newfd = kde_accept(m_sockfd, &sa, &len);
00394   if (newfd == -1)
00395     {
00396       if (errno == EAGAIN || errno == EWOULDBLOCK)
00397     setError(WouldBlock);
00398       else
00399     setError(UnknownError);
00400       return NULL;
00401     }
00402 
00403   return new KSocketDevice(newfd);
00404 }
00405 
00406 bool KSocketDevice::disconnect()
00407 {
00408   resetError();
00409 
00410   if (m_sockfd == -1)
00411     return false;       // can't create
00412 
00413   KSocketAddress address;
00414   address.setFamily(AF_UNSPEC);
00415   if (kde_connect(m_sockfd, address.address(), address.length()) == -1)
00416     {
00417       if (errno == EALREADY || errno == EINPROGRESS)
00418     {
00419       setError(InProgress);
00420       return false;
00421     }
00422       else if (errno == ECONNREFUSED)
00423     setError(ConnectionRefused);
00424       else if (errno == ENETDOWN || errno == ENETUNREACH ||
00425            errno == ENETRESET || errno == ECONNABORTED ||
00426            errno == ECONNRESET || errno == EHOSTDOWN ||
00427            errno == EHOSTUNREACH)
00428     setError(NetFailure);
00429       else
00430     setError(NotSupported);
00431 
00432       return false;
00433     }
00434 
00435   setOpenMode(QIODevice::Unbuffered | QIODevice::ReadWrite);
00436   return true;          // all is well
00437 }
00438 
00439 qint64 KSocketDevice::bytesAvailable() const
00440 {
00441   if (m_sockfd == -1)
00442     return -1;          // there's nothing to read in a closed socket
00443 
00444   int nchars;
00445   if (kde_ioctl(m_sockfd, FIONREAD, &nchars) == -1)
00446     return -1;          // error!
00447 
00448   return nchars;
00449 }
00450 
00451 qint64 KSocketDevice::waitForMore(int msecs, bool *timeout)
00452 {
00453   if (m_sockfd == -1)
00454     return -1;          // there won't ever be anything to read...
00455 
00456   bool input;
00457   if (!poll(&input, 0, 0, msecs, timeout))
00458     return -1;          // failed polling
00459 
00460   return bytesAvailable();
00461 }
00462 
00463 static int do_read_common(int sockfd, char *data, qint64 maxlen, KSocketAddress* from, ssize_t &retval, bool peek = false)
00464 {
00465   socklen_t len;
00466   if (from)
00467     {
00468       from->setLength(len = 128); // arbitrary length
00469       retval = ::recvfrom(sockfd, data, maxlen, peek ? MSG_PEEK : 0, from->address(), &len);
00470     }
00471   else
00472     retval = ::recvfrom(sockfd, data, maxlen, peek ? MSG_PEEK : 0, NULL, NULL);
00473 
00474   if (retval == -1)
00475     {
00476 #ifdef Q_WS_WIN
00477      if (WSAGetLastError() == WSAEWOULDBLOCK )
00478     return KSocketDevice::WouldBlock;
00479        else 
00480 #endif
00481       if (errno == EAGAIN || errno == EWOULDBLOCK )
00482     return KSocketDevice::WouldBlock;
00483       else
00484     return KSocketDevice::UnknownError;
00485     }
00486   if (retval == 0)
00487     return KSocketDevice::RemotelyDisconnected;
00488 
00489   if (from)
00490     from->setLength(len);
00491   return 0;
00492 }
00493 
00494 qint64 KSocketDevice::readData(char *data, qint64 maxlen, KSocketAddress *from)
00495 {
00496   resetError();
00497   if (m_sockfd == -1)
00498     return -1;          // nothing to do here
00499 
00500   if (data == 0L || maxlen == 0)
00501     return 0;           // user doesn't want to read
00502 
00503   ssize_t retval;
00504   int err = do_read_common(m_sockfd, data, maxlen, from, retval);
00505 
00506   if (err)
00507     {
00508       setError(static_cast<SocketError>(err));
00509       return -1;
00510     }
00511 
00512   return retval;
00513 }
00514 
00515 qint64 KSocketDevice::peekData(char *data, qint64 maxlen, KSocketAddress* from)
00516 {
00517   resetError();
00518   if (m_sockfd == -1)
00519     return -1;          // nothing to do here
00520 
00521   if (data == 0L || maxlen == 0)
00522     return 0;           // user doesn't want to read
00523 
00524   ssize_t retval;
00525   int err = do_read_common(m_sockfd, data, maxlen, from, retval, true);
00526 
00527   if (err)
00528     {
00529       setError(static_cast<SocketError>(err));
00530       return -1;
00531     }
00532 
00533   return retval;
00534 }
00535 
00536 qint64 KSocketDevice::writeData(const char *data, qint64 len, const KSocketAddress* to)
00537 {
00538   resetError();
00539   if (m_sockfd == -1)
00540     return -1;          // can't write to unopen socket
00541 
00542   if (data == 0L || len == 0)
00543     return 0;           // nothing to be written
00544 
00545   ssize_t retval;
00546   if (to != 0L)
00547     retval = ::sendto(m_sockfd, data, len, 0, to->address(), to->length());
00548   else
00549 #ifdef Q_WS_WIN
00550     retval = ::send(m_sockfd, data, len, 0);
00551 #else
00552     retval = ::write(m_sockfd, data, len);
00553 #endif
00554   if (retval == -1)
00555     {
00556       if (errno == EAGAIN || errno == EWOULDBLOCK)
00557     setError(WouldBlock);
00558       else
00559     setError(UnknownError);
00560       return -1;        // nothing written
00561     }
00562   else if (retval == 0)
00563     setError(RemotelyDisconnected);
00564 
00565   return retval;
00566 }
00567 
00568 KSocketAddress KSocketDevice::localAddress() const
00569 {
00570   if (m_sockfd == -1)
00571     return KSocketAddress();    // not open, empty value
00572 
00573   if (d->local.family() != AF_UNSPEC)
00574     return d->local;
00575 
00576   socklen_t len;
00577   KSocketAddress localAddress;
00578   localAddress.setLength(len = 32); // arbitrary value
00579   if (kde_getsockname(m_sockfd, localAddress.address(), &len) == -1)
00580     // error!
00581     return d->local = KSocketAddress();
00582 
00583 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
00584   len = localAddress.address()->sa_len;
00585 #endif
00586 
00587   if (len <= localAddress.length())
00588     {
00589       // it has fit already
00590       localAddress.setLength(len);
00591       return d->local = localAddress;
00592     }
00593 
00594   // no, the socket address is actually larger than we had anticipated
00595   // call again
00596   localAddress.setLength(len);
00597   if (kde_getsockname(m_sockfd, localAddress.address(), &len) == -1)
00598     // error!
00599     return d->local = KSocketAddress();
00600 
00601   return d->local = localAddress;
00602 }
00603 
00604 KSocketAddress KSocketDevice::peerAddress() const
00605 {
00606   if (m_sockfd == -1)
00607     return KSocketAddress();    // not open, empty value
00608 
00609   if (d->peer.family() != AF_UNSPEC)
00610     return d->peer;
00611 
00612   socklen_t len;
00613   KSocketAddress peerAddress;
00614   peerAddress.setLength(len = 32);  // arbitrary value
00615   if (kde_getpeername(m_sockfd, peerAddress.address(), &len) == -1)
00616     // error!
00617     return d->peer = KSocketAddress();
00618 
00619 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
00620   len = peerAddress.address()->sa_len;
00621 #endif
00622 
00623   if (len <= peerAddress.length())
00624     {
00625       // it has fit already
00626       peerAddress.setLength(len);
00627       return d->peer = peerAddress;
00628     }
00629 
00630   // no, the socket address is actually larger than we had anticipated
00631   // call again
00632   peerAddress.setLength(len);
00633   if (kde_getpeername(m_sockfd, peerAddress.address(), &len) == -1)
00634     // error!
00635     return d->peer = KSocketAddress();
00636 
00637   return d->peer = peerAddress;
00638 }
00639 
00640 KSocketAddress KSocketDevice::externalAddress() const
00641 {
00642   // for normal sockets, the externally visible address is the same
00643   // as the local address
00644   return localAddress();
00645 }
00646 
00647 QSocketNotifier* KSocketDevice::readNotifier() const
00648 {
00649   if (d->input)
00650     return d->input;
00651 
00652   QMutexLocker locker(mutex());
00653   if (d->input)
00654     return d->input;
00655 
00656   if (m_sockfd == -1)
00657     {
00658       // socket doesn't exist; can't create notifier
00659       return 0L;
00660     }
00661 
00662   return d->input = createNotifier(QSocketNotifier::Read);
00663 }
00664 
00665 QSocketNotifier* KSocketDevice::writeNotifier() const
00666 {
00667   if (d->output)
00668     return d->output;
00669 
00670   QMutexLocker locker(mutex());
00671   if (d->output)
00672     return d->output;
00673 
00674   if (m_sockfd == -1)
00675     {
00676       // socket doesn't exist; can't create notifier
00677       return 0L;
00678     }
00679 
00680   return d->output = createNotifier(QSocketNotifier::Write);
00681 }
00682 
00683 QSocketNotifier* KSocketDevice::exceptionNotifier() const
00684 {
00685   if (d->exception)
00686     return d->exception;
00687 
00688   QMutexLocker locker(mutex());
00689   if (d->exception)
00690     return d->exception;
00691 
00692   if (m_sockfd == -1)
00693     {
00694       // socket doesn't exist; can't create notifier
00695       return 0L;
00696     }
00697 
00698   return d->exception = createNotifier(QSocketNotifier::Exception);
00699 }
00700 
00701 bool KSocketDevice::poll(bool *input, bool *output, bool *exception,
00702              int timeout, bool* timedout)
00703 {
00704   if (m_sockfd == -1)
00705     {
00706       setError(NotCreated);
00707       return false;
00708     }
00709 
00710   resetError();
00711 #ifdef HAVE_POLL
00712   struct pollfd fds;
00713   fds.fd = m_sockfd;
00714   fds.events = 0;
00715 
00716   if (input)
00717     {
00718       fds.events |= POLLIN;
00719       *input = false;
00720     }
00721   if (output)
00722     {
00723       fds.events |= POLLOUT;
00724       *output = false;
00725     }
00726   if (exception)
00727     {
00728       fds.events |= POLLPRI;
00729       *exception = false;
00730     }
00731 
00732   int retval = ::poll(&fds, 1, timeout);
00733   if (retval == -1)
00734     {
00735       setError(UnknownError);
00736       return false;
00737     }
00738   if (retval == 0)
00739     {
00740       // timeout
00741       if (timedout)
00742     *timedout = true;
00743       return true;
00744     }
00745 
00746   if (input && fds.revents & POLLIN)
00747     *input = true;
00748   if (output && fds.revents & POLLOUT)
00749     *output = true;
00750   if (exception && fds.revents & POLLPRI)
00751     *exception = true;
00752   if (timedout)
00753     *timedout = false;
00754 
00755   return true;
00756 #else
00757   /*
00758    * We don't have poll(2). We'll have to make do with select(2).
00759    */
00760 
00761   fd_set readfds, writefds, exceptfds;
00762   fd_set *preadfds = 0L, *pwritefds = 0L, *pexceptfds = 0L;
00763 
00764   if (input)
00765     {
00766       preadfds = &readfds;
00767       FD_ZERO(preadfds);
00768       FD_SET(m_sockfd, preadfds);
00769       *input = false;
00770     }
00771   if (output)
00772     {
00773       pwritefds = &writefds;
00774       FD_ZERO(pwritefds);
00775       FD_SET(m_sockfd, pwritefds);
00776       *output = false;
00777     }
00778   if (exception)
00779     {
00780       pexceptfds = &exceptfds;
00781       FD_ZERO(pexceptfds);
00782       FD_SET(m_sockfd, pexceptfds);
00783       *exception = false;
00784     }
00785 
00786   int retval;
00787   if (timeout < 0)
00788     retval = select(m_sockfd + 1, preadfds, pwritefds, pexceptfds, 0L);
00789   else
00790     {
00791       // convert the milliseconds to timeval
00792       struct timeval tv;
00793       tv.tv_sec = timeout / 1000;
00794       tv.tv_usec = timeout % 1000 * 1000;
00795 
00796       retval = select(m_sockfd + 1, preadfds, pwritefds, pexceptfds, &tv);
00797     }
00798 
00799   if (retval == -1)
00800     {
00801       setError(UnknownError);
00802       return false;
00803     }
00804   if (retval == 0)
00805     {
00806       // timeout
00807       if (timedout)
00808     *timedout = true;
00809       return true;
00810     }
00811 
00812   if (input && FD_ISSET(m_sockfd, preadfds))
00813     *input = true;
00814   if (output && FD_ISSET(m_sockfd, pwritefds))
00815     *output = true;
00816   if (exception && FD_ISSET(m_sockfd, pexceptfds))
00817     *exception = true;
00818 
00819   return true;
00820 #endif
00821 }
00822 
00823 bool KSocketDevice::poll(int timeout, bool *timedout)
00824 {
00825   bool input, output, exception;
00826   return poll(&input, &output, &exception, timeout, timedout);
00827 }
00828 
00829 QSocketNotifier* KSocketDevice::createNotifier(QSocketNotifier::Type type) const
00830 {
00831   if (m_sockfd == -1)
00832     return 0L;
00833 
00834   return new QSocketNotifier(m_sockfd, type);
00835 }
00836 
00837 namespace
00838 {
00839   // simple class to avoid pointer stuff
00840   template<class T> class ptr
00841   {
00842     typedef T type;
00843     type* obj;
00844   public:
00845     ptr() : obj(0)
00846     { }
00847 
00848     ptr(const ptr<T>& other) : obj(other.obj)
00849     { }
00850 
00851     ptr(type* _obj) : obj(_obj)
00852     { }
00853 
00854     ~ptr()
00855     { }
00856 
00857     ptr<T>& operator=(const ptr<T>& other)
00858     { obj = other.obj; return *this; }
00859 
00860     ptr<T>& operator=(T* _obj)
00861     { obj = _obj; return  *this; }
00862 
00863     type* operator->() const { return obj; }
00864 
00865     operator T*() const { return obj; }
00866 
00867     bool isNull() const
00868     { return obj == 0; }
00869   };
00870 }
00871 
00872 static KSocketDeviceFactoryBase* defaultImplFactory;
00873 static QMutex defaultImplFactoryMutex;
00874 typedef QMap<int, KSocketDeviceFactoryBase* > factoryMap;
00875 static factoryMap factories;
00876 
00877 KSocketDevice* KSocketDevice::createDefault(KSocketBase* parent)
00878 {
00879   KSocketDevice* device = dynamic_cast<KSocketDevice*>(parent);
00880   if (device != 0L)
00881     return device;
00882 
00883   if (defaultImplFactory)
00884     return defaultImplFactory->create(parent);
00885 
00886   // the really default
00887   return new KSocketDevice(parent);
00888 }
00889 
00890 KSocketDevice* KSocketDevice::createDefault(KSocketBase* parent, int capabilities)
00891 {
00892   KSocketDevice* device = dynamic_cast<KSocketDevice*>(parent);
00893   if (device != 0L)
00894     return device;
00895 
00896   QMutexLocker locker(&defaultImplFactoryMutex);
00897   factoryMap::ConstIterator it = factories.constBegin();
00898   for ( ; it != factories.constEnd(); ++it)
00899     if ((it.key() & capabilities) == capabilities)
00900       // found a match
00901       return it.value()->create(parent);
00902 
00903   return 0L;            // no default
00904 }
00905 
00906 KSocketDeviceFactoryBase*
00907 KSocketDevice::setDefaultImpl(KSocketDeviceFactoryBase* factory)
00908 {
00909   QMutexLocker locker(&defaultImplFactoryMutex);
00910   KSocketDeviceFactoryBase* old = defaultImplFactory;
00911   defaultImplFactory = factory;
00912   return old;
00913 }
00914 
00915 void KSocketDevice::addNewImpl(KSocketDeviceFactoryBase* factory, int capabilities)
00916 {
00917   QMutexLocker locker(&defaultImplFactoryMutex);
00918   if (factories.contains(capabilities))
00919     delete factories[capabilities];
00920   factories.insert(capabilities, factory);
00921 }
00922 

KDECore

Skip menu "KDECore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.6.1
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal