• Skip to content
  • Skip to link menu
KDE 4.2 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
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     return true;        // we're already connected
00356       else if (errno == EALREADY || errno == EINPROGRESS)
00357     {
00358       setError(InProgress);
00359       return true;
00360     }
00361       else if (errno == ECONNREFUSED)
00362     setError(ConnectionRefused);
00363       else if (errno == ENETDOWN || errno == ENETUNREACH ||
00364            errno == ENETRESET || errno == ECONNABORTED ||
00365            errno == ECONNRESET || errno == EHOSTDOWN ||
00366            errno == EHOSTUNREACH)
00367     setError(NetFailure);
00368       else
00369     setError(NotSupported);
00370 
00371       return false;
00372     }
00373 
00374   KActiveSocketBase::open(Unbuffered | mode);
00375   return true;          // all is well
00376 }
00377 
00378 KSocketDevice* KSocketDevice::accept()
00379 {
00380   if (m_sockfd == -1)
00381     {
00382       // can't accept without a socket
00383       setError(NotCreated);
00384       return 0L;
00385     }
00386 
00387   struct sockaddr sa;
00388   socklen_t len = sizeof(sa);
00389   int newfd = kde_accept(m_sockfd, &sa, &len);
00390   if (newfd == -1)
00391     {
00392       if (errno == EAGAIN || errno == EWOULDBLOCK)
00393     setError(WouldBlock);
00394       else
00395     setError(UnknownError);
00396       return NULL;
00397     }
00398 
00399   return new KSocketDevice(newfd);
00400 }
00401 
00402 bool KSocketDevice::disconnect()
00403 {
00404   resetError();
00405 
00406   if (m_sockfd == -1)
00407     return false;       // can't create
00408 
00409   KSocketAddress address;
00410   address.setFamily(AF_UNSPEC);
00411   if (kde_connect(m_sockfd, address.address(), address.length()) == -1)
00412     {
00413       if (errno == EALREADY || errno == EINPROGRESS)
00414     {
00415       setError(InProgress);
00416       return false;
00417     }
00418       else if (errno == ECONNREFUSED)
00419     setError(ConnectionRefused);
00420       else if (errno == ENETDOWN || errno == ENETUNREACH ||
00421            errno == ENETRESET || errno == ECONNABORTED ||
00422            errno == ECONNRESET || errno == EHOSTDOWN ||
00423            errno == EHOSTUNREACH)
00424     setError(NetFailure);
00425       else
00426     setError(NotSupported);
00427 
00428       return false;
00429     }
00430 
00431   setOpenMode(QIODevice::Unbuffered | QIODevice::ReadWrite);
00432   return true;          // all is well
00433 }
00434 
00435 qint64 KSocketDevice::bytesAvailable() const
00436 {
00437   if (m_sockfd == -1)
00438     return -1;          // there's nothing to read in a closed socket
00439 
00440   int nchars;
00441   if (kde_ioctl(m_sockfd, FIONREAD, &nchars) == -1)
00442     return -1;          // error!
00443 
00444   return nchars;
00445 }
00446 
00447 qint64 KSocketDevice::waitForMore(int msecs, bool *timeout)
00448 {
00449   if (m_sockfd == -1)
00450     return -1;          // there won't ever be anything to read...
00451 
00452   bool input;
00453   if (!poll(&input, 0, 0, msecs, timeout))
00454     return -1;          // failed polling
00455 
00456   return bytesAvailable();
00457 }
00458 
00459 static int do_read_common(int sockfd, char *data, qint64 maxlen, KSocketAddress* from, ssize_t &retval, bool peek = false)
00460 {
00461   socklen_t len;
00462   if (from)
00463     {
00464       from->setLength(len = 128); // arbitrary length
00465       retval = ::recvfrom(sockfd, data, maxlen, peek ? MSG_PEEK : 0, from->address(), &len);
00466     }
00467   else
00468     retval = ::recvfrom(sockfd, data, maxlen, peek ? MSG_PEEK : 0, NULL, NULL);
00469 
00470   if (retval == -1)
00471     {
00472 #ifdef Q_WS_WIN
00473      if (WSAGetLastError() == WSAEWOULDBLOCK )
00474     return KSocketDevice::WouldBlock;
00475        else 
00476 #endif
00477       if (errno == EAGAIN || errno == EWOULDBLOCK )
00478     return KSocketDevice::WouldBlock;
00479       else
00480     return KSocketDevice::UnknownError;
00481     }
00482   if (retval == 0)
00483     return KSocketDevice::RemotelyDisconnected;
00484 
00485   if (from)
00486     from->setLength(len);
00487   return 0;
00488 }
00489 
00490 qint64 KSocketDevice::readData(char *data, qint64 maxlen, KSocketAddress *from)
00491 {
00492   resetError();
00493   if (m_sockfd == -1)
00494     return -1;          // nothing to do here
00495 
00496   if (data == 0L || maxlen == 0)
00497     return 0;           // user doesn't want to read
00498 
00499   ssize_t retval;
00500   int err = do_read_common(m_sockfd, data, maxlen, from, retval);
00501 
00502   if (err)
00503     {
00504       setError(static_cast<SocketError>(err));
00505       return -1;
00506     }
00507 
00508   return retval;
00509 }
00510 
00511 qint64 KSocketDevice::peekData(char *data, qint64 maxlen, KSocketAddress* from)
00512 {
00513   resetError();
00514   if (m_sockfd == -1)
00515     return -1;          // nothing to do here
00516 
00517   if (data == 0L || maxlen == 0)
00518     return 0;           // user doesn't want to read
00519 
00520   ssize_t retval;
00521   int err = do_read_common(m_sockfd, data, maxlen, from, retval, true);
00522 
00523   if (err)
00524     {
00525       setError(static_cast<SocketError>(err));
00526       return -1;
00527     }
00528 
00529   return retval;
00530 }
00531 
00532 qint64 KSocketDevice::writeData(const char *data, qint64 len, const KSocketAddress* to)
00533 {
00534   resetError();
00535   if (m_sockfd == -1)
00536     return -1;          // can't write to unopen socket
00537 
00538   if (data == 0L || len == 0)
00539     return 0;           // nothing to be written
00540 
00541   ssize_t retval;
00542   if (to != 0L)
00543     retval = ::sendto(m_sockfd, data, len, 0, to->address(), to->length());
00544   else
00545 #ifdef Q_WS_WIN
00546     retval = ::send(m_sockfd, data, len, 0);
00547 #else
00548     retval = ::write(m_sockfd, data, len);
00549 #endif
00550   if (retval == -1)
00551     {
00552       if (errno == EAGAIN || errno == EWOULDBLOCK)
00553     setError(WouldBlock);
00554       else
00555     setError(UnknownError);
00556       return -1;        // nothing written
00557     }
00558   else if (retval == 0)
00559     setError(RemotelyDisconnected);
00560 
00561   return retval;
00562 }
00563 
00564 KSocketAddress KSocketDevice::localAddress() const
00565 {
00566   if (m_sockfd == -1)
00567     return KSocketAddress();    // not open, empty value
00568 
00569   if (d->local.family() != AF_UNSPEC)
00570     return d->local;
00571 
00572   socklen_t len;
00573   KSocketAddress localAddress;
00574   localAddress.setLength(len = 32); // arbitrary value
00575   if (kde_getsockname(m_sockfd, localAddress.address(), &len) == -1)
00576     // error!
00577     return d->local = KSocketAddress();
00578 
00579 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
00580   len = localAddress.address()->sa_len;
00581 #endif
00582 
00583   if (len <= localAddress.length())
00584     {
00585       // it has fit already
00586       localAddress.setLength(len);
00587       return d->local = localAddress;
00588     }
00589 
00590   // no, the socket address is actually larger than we had anticipated
00591   // call again
00592   localAddress.setLength(len);
00593   if (kde_getsockname(m_sockfd, localAddress.address(), &len) == -1)
00594     // error!
00595     return d->local = KSocketAddress();
00596 
00597   return d->local = localAddress;
00598 }
00599 
00600 KSocketAddress KSocketDevice::peerAddress() const
00601 {
00602   if (m_sockfd == -1)
00603     return KSocketAddress();    // not open, empty value
00604 
00605   if (d->peer.family() != AF_UNSPEC)
00606     return d->peer;
00607 
00608   socklen_t len;
00609   KSocketAddress peerAddress;
00610   peerAddress.setLength(len = 32);  // arbitrary value
00611   if (kde_getpeername(m_sockfd, peerAddress.address(), &len) == -1)
00612     // error!
00613     return d->peer = KSocketAddress();
00614 
00615 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
00616   len = peerAddress.address()->sa_len;
00617 #endif
00618 
00619   if (len <= peerAddress.length())
00620     {
00621       // it has fit already
00622       peerAddress.setLength(len);
00623       return d->peer = peerAddress;
00624     }
00625 
00626   // no, the socket address is actually larger than we had anticipated
00627   // call again
00628   peerAddress.setLength(len);
00629   if (kde_getpeername(m_sockfd, peerAddress.address(), &len) == -1)
00630     // error!
00631     return d->peer = KSocketAddress();
00632 
00633   return d->peer = peerAddress;
00634 }
00635 
00636 KSocketAddress KSocketDevice::externalAddress() const
00637 {
00638   // for normal sockets, the externally visible address is the same
00639   // as the local address
00640   return localAddress();
00641 }
00642 
00643 QSocketNotifier* KSocketDevice::readNotifier() const
00644 {
00645   if (d->input)
00646     return d->input;
00647 
00648   QMutexLocker locker(mutex());
00649   if (d->input)
00650     return d->input;
00651 
00652   if (m_sockfd == -1)
00653     {
00654       // socket doesn't exist; can't create notifier
00655       return 0L;
00656     }
00657 
00658   return d->input = createNotifier(QSocketNotifier::Read);
00659 }
00660 
00661 QSocketNotifier* KSocketDevice::writeNotifier() const
00662 {
00663   if (d->output)
00664     return d->output;
00665 
00666   QMutexLocker locker(mutex());
00667   if (d->output)
00668     return d->output;
00669 
00670   if (m_sockfd == -1)
00671     {
00672       // socket doesn't exist; can't create notifier
00673       return 0L;
00674     }
00675 
00676   return d->output = createNotifier(QSocketNotifier::Write);
00677 }
00678 
00679 QSocketNotifier* KSocketDevice::exceptionNotifier() const
00680 {
00681   if (d->exception)
00682     return d->exception;
00683 
00684   QMutexLocker locker(mutex());
00685   if (d->exception)
00686     return d->exception;
00687 
00688   if (m_sockfd == -1)
00689     {
00690       // socket doesn't exist; can't create notifier
00691       return 0L;
00692     }
00693 
00694   return d->exception = createNotifier(QSocketNotifier::Exception);
00695 }
00696 
00697 bool KSocketDevice::poll(bool *input, bool *output, bool *exception,
00698              int timeout, bool* timedout)
00699 {
00700   if (m_sockfd == -1)
00701     {
00702       setError(NotCreated);
00703       return false;
00704     }
00705 
00706   resetError();
00707 #ifdef HAVE_POLL
00708   struct pollfd fds;
00709   fds.fd = m_sockfd;
00710   fds.events = 0;
00711 
00712   if (input)
00713     {
00714       fds.events |= POLLIN;
00715       *input = false;
00716     }
00717   if (output)
00718     {
00719       fds.events |= POLLOUT;
00720       *output = false;
00721     }
00722   if (exception)
00723     {
00724       fds.events |= POLLPRI;
00725       *exception = false;
00726     }
00727 
00728   int retval = ::poll(&fds, 1, timeout);
00729   if (retval == -1)
00730     {
00731       setError(UnknownError);
00732       return false;
00733     }
00734   if (retval == 0)
00735     {
00736       // timeout
00737       if (timedout)
00738     *timedout = true;
00739       return true;
00740     }
00741 
00742   if (input && fds.revents & POLLIN)
00743     *input = true;
00744   if (output && fds.revents & POLLOUT)
00745     *output = true;
00746   if (exception && fds.revents & POLLPRI)
00747     *exception = true;
00748   if (timedout)
00749     *timedout = false;
00750 
00751   return true;
00752 #else
00753   /*
00754    * We don't have poll(2). We'll have to make do with select(2).
00755    */
00756 
00757   fd_set readfds, writefds, exceptfds;
00758   fd_set *preadfds = 0L, *pwritefds = 0L, *pexceptfds = 0L;
00759 
00760   if (input)
00761     {
00762       preadfds = &readfds;
00763       FD_ZERO(preadfds);
00764       FD_SET(m_sockfd, preadfds);
00765       *input = false;
00766     }
00767   if (output)
00768     {
00769       pwritefds = &writefds;
00770       FD_ZERO(pwritefds);
00771       FD_SET(m_sockfd, pwritefds);
00772       *output = false;
00773     }
00774   if (exception)
00775     {
00776       pexceptfds = &exceptfds;
00777       FD_ZERO(pexceptfds);
00778       FD_SET(m_sockfd, pexceptfds);
00779       *exception = false;
00780     }
00781 
00782   int retval;
00783   if (timeout < 0)
00784     retval = select(m_sockfd + 1, preadfds, pwritefds, pexceptfds, 0L);
00785   else
00786     {
00787       // convert the milliseconds to timeval
00788       struct timeval tv;
00789       tv.tv_sec = timeout / 1000;
00790       tv.tv_usec = timeout % 1000 * 1000;
00791 
00792       retval = select(m_sockfd + 1, preadfds, pwritefds, pexceptfds, &tv);
00793     }
00794 
00795   if (retval == -1)
00796     {
00797       setError(UnknownError);
00798       return false;
00799     }
00800   if (retval == 0)
00801     {
00802       // timeout
00803       if (timedout)
00804     *timedout = true;
00805       return true;
00806     }
00807 
00808   if (input && FD_ISSET(m_sockfd, preadfds))
00809     *input = true;
00810   if (output && FD_ISSET(m_sockfd, pwritefds))
00811     *output = true;
00812   if (exception && FD_ISSET(m_sockfd, pexceptfds))
00813     *exception = true;
00814 
00815   return true;
00816 #endif
00817 }
00818 
00819 bool KSocketDevice::poll(int timeout, bool *timedout)
00820 {
00821   bool input, output, exception;
00822   return poll(&input, &output, &exception, timeout, timedout);
00823 }
00824 
00825 QSocketNotifier* KSocketDevice::createNotifier(QSocketNotifier::Type type) const
00826 {
00827   if (m_sockfd == -1)
00828     return 0L;
00829 
00830   return new QSocketNotifier(m_sockfd, type);
00831 }
00832 
00833 namespace
00834 {
00835   // simple class to avoid pointer stuff
00836   template<class T> class ptr
00837   {
00838     typedef T type;
00839     type* obj;
00840   public:
00841     ptr() : obj(0)
00842     { }
00843 
00844     ptr(const ptr<T>& other) : obj(other.obj)
00845     { }
00846 
00847     ptr(type* _obj) : obj(_obj)
00848     { }
00849 
00850     ~ptr()
00851     { }
00852 
00853     ptr<T>& operator=(const ptr<T>& other)
00854     { obj = other.obj; return *this; }
00855 
00856     ptr<T>& operator=(T* _obj)
00857     { obj = _obj; return  *this; }
00858 
00859     type* operator->() const { return obj; }
00860 
00861     operator T*() const { return obj; }
00862 
00863     bool isNull() const
00864     { return obj == 0; }
00865   };
00866 }
00867 
00868 static KSocketDeviceFactoryBase* defaultImplFactory;
00869 static QMutex defaultImplFactoryMutex;
00870 typedef QMap<int, KSocketDeviceFactoryBase* > factoryMap;
00871 static factoryMap factories;
00872 
00873 KSocketDevice* KSocketDevice::createDefault(KSocketBase* parent)
00874 {
00875   KSocketDevice* device = dynamic_cast<KSocketDevice*>(parent);
00876   if (device != 0L)
00877     return device;
00878 
00879   if (defaultImplFactory)
00880     return defaultImplFactory->create(parent);
00881 
00882   // the really default
00883   return new KSocketDevice(parent);
00884 }
00885 
00886 KSocketDevice* KSocketDevice::createDefault(KSocketBase* parent, int capabilities)
00887 {
00888   KSocketDevice* device = dynamic_cast<KSocketDevice*>(parent);
00889   if (device != 0L)
00890     return device;
00891 
00892   QMutexLocker locker(&defaultImplFactoryMutex);
00893   factoryMap::ConstIterator it = factories.constBegin();
00894   for ( ; it != factories.constEnd(); ++it)
00895     if ((it.key() & capabilities) == capabilities)
00896       // found a match
00897       return it.value()->create(parent);
00898 
00899   return 0L;            // no default
00900 }
00901 
00902 KSocketDeviceFactoryBase*
00903 KSocketDevice::setDefaultImpl(KSocketDeviceFactoryBase* factory)
00904 {
00905   QMutexLocker locker(&defaultImplFactoryMutex);
00906   KSocketDeviceFactoryBase* old = defaultImplFactory;
00907   defaultImplFactory = factory;
00908   return old;
00909 }
00910 
00911 void KSocketDevice::addNewImpl(KSocketDeviceFactoryBase* factory, int capabilities)
00912 {
00913   QMutexLocker locker(&defaultImplFactoryMutex);
00914   if (factories.contains(capabilities))
00915     delete factories[capabilities];
00916   factories.insert(capabilities, factory);
00917 }
00918 

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
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.7
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