kdecore Library API Documentation

ksocketdevice.cpp

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   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   if (retval == 0)
00405     return KSocketDevice::RemotelyDisconnected;
00406 
00407   if (from)
00408     from->setLength(len);
00409   return 0;
00410 }
00411 
00412 Q_LONG KSocketDevice::readBlock(char *data, Q_ULONG maxlen)
00413 {
00414   resetError();
00415   if (m_sockfd == -1)
00416     return -1;
00417 
00418   if (maxlen == 0 || data == 0L)
00419     return 0;           // can't read
00420 
00421   ssize_t retval;
00422   int err = do_read_common(m_sockfd, data, maxlen, 0L, retval);
00423 
00424   if (err)
00425     {
00426       setError(IO_ReadError, static_cast<SocketError>(err));
00427       return -1;
00428     }
00429 
00430   return retval;
00431 }
00432 
00433 Q_LONG KSocketDevice::readBlock(char *data, Q_ULONG maxlen, KSocketAddress &from)
00434 {
00435   resetError();
00436   if (m_sockfd == -1)
00437     return -1;          // nothing to do here
00438 
00439   if (data == 0L || maxlen == 0)
00440     return 0;           // user doesn't want to read
00441 
00442   ssize_t retval;
00443   int err = do_read_common(m_sockfd, data, maxlen, &from, retval);
00444 
00445   if (err)
00446     {
00447       setError(IO_ReadError, static_cast<SocketError>(err));
00448       return -1;
00449     }
00450 
00451   return retval;
00452 }
00453 
00454 Q_LONG KSocketDevice::peekBlock(char *data, Q_ULONG maxlen)
00455 {
00456   resetError();
00457   if (m_sockfd == -1)
00458     return -1;
00459 
00460   if (maxlen == 0 || data == 0L)
00461     return 0;           // can't read
00462 
00463   ssize_t retval;
00464   int err = do_read_common(m_sockfd, data, maxlen, 0L, retval, true);
00465 
00466   if (err)
00467     {
00468       setError(IO_ReadError, static_cast<SocketError>(err));
00469       return -1;
00470     }
00471 
00472   return retval;
00473 }
00474 
00475 Q_LONG KSocketDevice::peekBlock(char *data, Q_ULONG maxlen, KSocketAddress& from)
00476 {
00477   resetError();
00478   if (m_sockfd == -1)
00479     return -1;          // nothing to do here
00480 
00481   if (data == 0L || maxlen == 0)
00482     return 0;           // user doesn't want to read
00483 
00484   ssize_t retval;
00485   int err = do_read_common(m_sockfd, data, maxlen, &from, retval, true);
00486 
00487   if (err)
00488     {
00489       setError(IO_ReadError, static_cast<SocketError>(err));
00490       return -1;
00491     }
00492 
00493   return retval;
00494 }
00495 
00496 Q_LONG KSocketDevice::writeBlock(const char *data, Q_ULONG len)
00497 {
00498   return writeBlock(data, len, KSocketAddress());
00499 }
00500 
00501 Q_LONG KSocketDevice::writeBlock(const char *data, Q_ULONG len, const KSocketAddress& to)
00502 {
00503   resetError();
00504   if (m_sockfd == -1)
00505     return -1;          // can't write to unopen socket
00506 
00507   if (data == 0L || len == 0)
00508     return 0;           // nothing to be written
00509 
00510   ssize_t retval = ::sendto(m_sockfd, data, len, 0, to.address(), to.length());
00511   if (retval == -1)
00512     {
00513       if (errno == EAGAIN || errno == EWOULDBLOCK)
00514     setError(IO_WriteError, WouldBlock);
00515       else
00516     setError(IO_WriteError, UnknownError);
00517       return -1;        // nothing written
00518     }
00519   else if (retval == 0)
00520     setError(IO_WriteError, RemotelyDisconnected);
00521 
00522   return retval;
00523 }
00524 
00525 KSocketAddress KSocketDevice::localAddress() const
00526 {
00527   if (m_sockfd == -1)
00528     return KSocketAddress();    // not open, empty value
00529 
00530   socklen_t len;
00531   KSocketAddress localAddress;
00532   localAddress.setLength(len = 32); // arbitrary value
00533   if (kde_getsockname(m_sockfd, localAddress.address(), &len) == -1)
00534     // error!
00535     return KSocketAddress();
00536 
00537   if (len <= localAddress.length())
00538     {
00539       // it has fit already
00540       localAddress.setLength(len);
00541       return localAddress;
00542     }
00543 
00544   // no, the socket address is actually larger than we had anticipated
00545   // call again
00546   localAddress.setLength(len);
00547   if (kde_getsockname(m_sockfd, localAddress.address(), &len) == -1)
00548     // error!
00549     return KSocketAddress();
00550 
00551   return localAddress;
00552 }
00553 
00554 KSocketAddress KSocketDevice::peerAddress() const
00555 {
00556   if (m_sockfd == -1)
00557     return KSocketAddress();    // not open, empty value
00558 
00559   socklen_t len;
00560   KSocketAddress peerAddress;
00561   peerAddress.setLength(len = 32);  // arbitrary value
00562   if (kde_getpeername(m_sockfd, peerAddress.address(), &len) == -1)
00563     // error!
00564     return KSocketAddress();
00565 
00566   if (len <= peerAddress.length())
00567     {
00568       // it has fit already
00569       peerAddress.setLength(len);
00570       return peerAddress;
00571     }
00572 
00573   // no, the socket address is actually larger than we had anticipated
00574   // call again
00575   peerAddress.setLength(len);
00576   if (kde_getpeername(m_sockfd, peerAddress.address(), &len) == -1)
00577     // error!
00578     return KSocketAddress();
00579 
00580   return peerAddress;
00581 }
00582 
00583 KSocketAddress KSocketDevice::externalAddress() const
00584 {
00585   // for normal sockets, the externally visible address is the same
00586   // as the local address
00587   return localAddress();
00588 }
00589 
00590 QSocketNotifier* KSocketDevice::readNotifier() const
00591 {
00592   if (d->input)
00593     return d->input;
00594 
00595   QMutexLocker locker(mutex());
00596   if (d->input)
00597     return d->input;
00598 
00599   if (m_sockfd == -1)
00600     {
00601       // socket doesn't exist; can't create notifier
00602       return 0L;
00603     }
00604 
00605   return d->input = createNotifier(QSocketNotifier::Read);
00606 }
00607 
00608 QSocketNotifier* KSocketDevice::writeNotifier() const
00609 {
00610   if (d->output)
00611     return d->output;
00612 
00613   QMutexLocker locker(mutex());
00614   if (d->output)
00615     return d->output;
00616 
00617   if (m_sockfd == -1)
00618     {
00619       // socket doesn't exist; can't create notifier
00620       return 0L;
00621     }
00622 
00623   return d->output = createNotifier(QSocketNotifier::Write);
00624 }
00625 
00626 QSocketNotifier* KSocketDevice::exceptionNotifier() const
00627 {
00628   if (d->exception)
00629     return d->exception;
00630 
00631   QMutexLocker locker(mutex());
00632   if (d->exception)
00633     return d->exception;
00634 
00635   if (m_sockfd == -1)
00636     {
00637       // socket doesn't exist; can't create notifier
00638       return 0L;
00639     }
00640 
00641   return d->exception = createNotifier(QSocketNotifier::Exception);
00642 }
00643 
00644 bool KSocketDevice::poll(bool *input, bool *output, bool *exception,
00645              int timeout, bool* timedout)
00646 {
00647   if (m_sockfd == -1)
00648     {
00649       setError(IO_UnspecifiedError, NotCreated);
00650       return false;
00651     }
00652 
00653   resetError();
00654 #ifdef HAVE_POLL
00655   struct pollfd fds;
00656   fds.fd = m_sockfd;
00657   fds.events = 0;
00658 
00659   if (input)
00660     {
00661       fds.events |= POLLIN;
00662       *input = false;
00663     }
00664   if (output)
00665     {
00666       fds.events |= POLLOUT;
00667       *output = false;
00668     }
00669   if (exception)
00670     {
00671       fds.events |= POLLPRI;
00672       *exception = false;
00673     }
00674 
00675   int retval = ::poll(&fds, 1, timeout);
00676   if (retval == -1)
00677     {
00678       setError(IO_UnspecifiedError, UnknownError);
00679       return false;
00680     }
00681   if (retval == 0)
00682     {
00683       // timeout
00684       if (timedout)
00685     *timedout = true;
00686       return true;
00687     }
00688 
00689   if (input && fds.revents & POLLIN)
00690     *input = true;
00691   if (output && fds.revents & POLLOUT)
00692     *output = true;
00693   if (exception && fds.revents & POLLPRI)
00694     *exception = true;
00695   if (timedout)
00696     *timedout = false;
00697 
00698   return true;
00699 #else
00700   /*
00701    * We don't have poll(2). We'll have to make do with select(2).
00702    */
00703 
00704   fd_set readfds, writefds, exceptfds;
00705   fd_set *preadfds = 0L, *pwritefds = 0L, *pexceptfds = 0L;
00706 
00707   if (input)
00708     {
00709       preadfds = &readfds;
00710       FD_ZERO(preadfds);
00711       FD_SET(m_sockfd, preadfds);
00712       *input = false;
00713     }
00714   if (output)
00715     {
00716       pwritefds = &writefds;
00717       FD_ZERO(pwritefds);
00718       FD_SET(m_sockfd, pwritefds);
00719       *output = false;
00720     }
00721   if (exception)
00722     {
00723       pexceptfds = &exceptfds;
00724       FD_ZERO(pexceptfds);
00725       FD_SET(m_sockfd, pexceptfds);
00726       *exception = false;
00727     }
00728 
00729   int retval;
00730   if (timeout < 0)
00731     retval = select(m_sockfd + 1, preadfds, pwritefds, pexceptfds, 0L);
00732   else
00733     {
00734       // convert the milliseconds to timeval
00735       struct timeval tv;
00736       tv.tv_sec = timeout / 1000;
00737       tv.tv_usec = timeout % 1000 * 1000;
00738 
00739       retval = select(m_sockfd + 1, preadfds, pwritefds, pexceptfds, &tv);
00740     }
00741 
00742   if (retval == -1)
00743     {
00744       setError(IO_UnspecifiedError, UnknownError);
00745       return false;
00746     }
00747   if (retval == 0)
00748     {
00749       // timeout
00750       if (timedout)
00751     *timedout = true;
00752       return true;
00753     }
00754 
00755   if (input && FD_ISSET(m_sockfd, preadfds))
00756     *input = true;
00757   if (output && FD_ISSET(m_sockfd, pwritefds))
00758     *output = true;
00759   if (exception && FD_ISSET(m_sockfd, pexceptfds))
00760     *exception = true;
00761 
00762   return true;
00763 #endif
00764 }
00765 
00766 bool KSocketDevice::poll(int timeout, bool *timedout)
00767 {
00768   bool input, output, exception;
00769   return poll(&input, &output, &exception, timeout, timedout);
00770 }
00771 
00772 QSocketNotifier* KSocketDevice::createNotifier(QSocketNotifier::Type type) const
00773 {
00774   if (m_sockfd == -1)
00775     return 0L;
00776 
00777   return new QSocketNotifier(m_sockfd, type);
00778 }
00779 
00780 namespace
00781 {
00782   // simple class to avoid pointer stuff
00783   template<class T> class ptr
00784   {
00785     typedef T type;
00786     type* obj;
00787   public:
00788     ptr() : obj(0)
00789     { }
00790 
00791     ptr(const ptr<T>& other) : obj(other.obj)
00792     { }
00793 
00794     ptr(type* _obj) : obj(_obj)
00795     { }
00796 
00797     ~ptr()
00798     { }
00799 
00800     ptr<T>& operator=(const ptr<T>& other)
00801     { obj = other.obj; return *this; }
00802 
00803     ptr<T>& operator=(T* _obj)
00804     { obj = _obj; return  *this; }
00805 
00806     type* operator->() const { return obj; }
00807 
00808     operator T*() const { return obj; }
00809 
00810     bool isNull() const
00811     { return obj == 0; }
00812   };
00813 }
00814 
00815 static KSocketDeviceFactoryBase* defaultImplFactory;
00816 static QMutex defaultImplFactoryMutex;
00817 typedef QMap<int, KSocketDeviceFactoryBase* > factoryMap;
00818 static factoryMap factories;
00819  
00820 KSocketDevice* KSocketDevice::createDefault(KSocketBase* parent)
00821 {
00822   KSocketDevice* device = dynamic_cast<KSocketDevice*>(parent);
00823   if (device != 0L)
00824     return device;
00825 
00826   KSocksSocketDevice::initSocks();
00827 
00828   if (defaultImplFactory)
00829     return defaultImplFactory->create(parent);
00830 
00831   // the really default
00832   return new KSocketDevice(parent);
00833 }
00834 
00835 KSocketDevice* KSocketDevice::createDefault(KSocketBase* parent, int capabilities)
00836 {
00837   KSocketDevice* device = dynamic_cast<KSocketDevice*>(parent);
00838   if (device != 0L)
00839     return device;
00840 
00841   QMutexLocker locker(&defaultImplFactoryMutex);
00842   factoryMap::ConstIterator it = factories.constBegin();
00843   for ( ; it != factories.constEnd(); ++it)
00844     if ((it.key() & capabilities) == capabilities)
00845       // found a match
00846       return it.data()->create(parent);
00847 
00848   return 0L;            // no default
00849 }
00850 
00851 KSocketDeviceFactoryBase*
00852 KSocketDevice::setDefaultImpl(KSocketDeviceFactoryBase* factory)
00853 {
00854   QMutexLocker locker(&defaultImplFactoryMutex);
00855   KSocketDeviceFactoryBase* old = defaultImplFactory;
00856   defaultImplFactory = factory;
00857   return old;
00858 }
00859 
00860 void KSocketDevice::addNewImpl(KSocketDeviceFactoryBase* factory, int capabilities)
00861 {
00862   QMutexLocker locker(&defaultImplFactoryMutex);
00863   if (factories.contains(capabilities))
00864     delete factories[capabilities];
00865   factories.insert(capabilities, factory);
00866 }
00867 
KDE Logo
This file is part of the documentation for kdecore Library Version 3.4.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Feb 8 08:00:49 2006 by doxygen 1.4.4 written by Dimitri van Heesch, © 1997-2003