kdecore Library API Documentation

ksocketdevice.cpp

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