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

KDECore

ksocketdevice.cpp

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

KDECore

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

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
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