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