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   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   if (len <= localAddress.length())
00546     {
00547       // it has fit already
00548       localAddress.setLength(len);
00549       return d->local = localAddress;
00550     }
00551 
00552   // no, the socket address is actually larger than we had anticipated
00553   // call again
00554   localAddress.setLength(len);
00555   if (kde_getsockname(m_sockfd, localAddress.address(), &len) == -1)
00556     // error!
00557     return d->local = KSocketAddress();
00558 
00559   return d->local = localAddress;
00560 }
00561 
00562 KSocketAddress KSocketDevice::peerAddress() const
00563 {
00564   if (m_sockfd == -1)
00565     return KSocketAddress();    // not open, empty value
00566 
00567   if (d->peer.family() != AF_UNSPEC)
00568     return d->peer;
00569 
00570   socklen_t len;
00571   KSocketAddress peerAddress;
00572   peerAddress.setLength(len = 32);  // arbitrary value
00573   if (kde_getpeername(m_sockfd, peerAddress.address(), &len) == -1)
00574     // error!
00575     return d->peer = KSocketAddress();
00576 
00577   if (len <= peerAddress.length())
00578     {
00579       // it has fit already
00580       peerAddress.setLength(len);
00581       return d->peer = peerAddress;
00582     }
00583 
00584   // no, the socket address is actually larger than we had anticipated
00585   // call again
00586   peerAddress.setLength(len);
00587   if (kde_getpeername(m_sockfd, peerAddress.address(), &len) == -1)
00588     // error!
00589     return d->peer = KSocketAddress();
00590 
00591   return d->peer = peerAddress;
00592 }
00593 
00594 KSocketAddress KSocketDevice::externalAddress() const
00595 {
00596   // for normal sockets, the externally visible address is the same
00597   // as the local address
00598   return localAddress();
00599 }
00600 
00601 QSocketNotifier* KSocketDevice::readNotifier() const
00602 {
00603   if (d->input)
00604     return d->input;
00605 
00606   QMutexLocker locker(mutex());
00607   if (d->input)
00608     return d->input;
00609 
00610   if (m_sockfd == -1)
00611     {
00612       // socket doesn't exist; can't create notifier
00613       return 0L;
00614     }
00615 
00616   return d->input = createNotifier(QSocketNotifier::Read);
00617 }
00618 
00619 QSocketNotifier* KSocketDevice::writeNotifier() const
00620 {
00621   if (d->output)
00622     return d->output;
00623 
00624   QMutexLocker locker(mutex());
00625   if (d->output)
00626     return d->output;
00627 
00628   if (m_sockfd == -1)
00629     {
00630       // socket doesn't exist; can't create notifier
00631       return 0L;
00632     }
00633 
00634   return d->output = createNotifier(QSocketNotifier::Write);
00635 }
00636 
00637 QSocketNotifier* KSocketDevice::exceptionNotifier() const
00638 {
00639   if (d->exception)
00640     return d->exception;
00641 
00642   QMutexLocker locker(mutex());
00643   if (d->exception)
00644     return d->exception;
00645 
00646   if (m_sockfd == -1)
00647     {
00648       // socket doesn't exist; can't create notifier
00649       return 0L;
00650     }
00651 
00652   return d->exception = createNotifier(QSocketNotifier::Exception);
00653 }
00654 
00655 bool KSocketDevice::poll(bool *input, bool *output, bool *exception,
00656              int timeout, bool* timedout)
00657 {
00658   if (m_sockfd == -1)
00659     {
00660       setError(IO_UnspecifiedError, NotCreated);
00661       return false;
00662     }
00663 
00664   resetError();
00665 #ifdef HAVE_POLL
00666   struct pollfd fds;
00667   fds.fd = m_sockfd;
00668   fds.events = 0;
00669 
00670   if (input)
00671     {
00672       fds.events |= POLLIN;
00673       *input = false;
00674     }
00675   if (output)
00676     {
00677       fds.events |= POLLOUT;
00678       *output = false;
00679     }
00680   if (exception)
00681     {
00682       fds.events |= POLLPRI;
00683       *exception = false;
00684     }
00685 
00686   int retval = ::poll(&fds, 1, timeout);
00687   if (retval == -1)
00688     {
00689       setError(IO_UnspecifiedError, UnknownError);
00690       return false;
00691     }
00692   if (retval == 0)
00693     {
00694       // timeout
00695       if (timedout)
00696     *timedout = true;
00697       return true;
00698     }
00699 
00700   if (input && fds.revents & POLLIN)
00701     *input = true;
00702   if (output && fds.revents & POLLOUT)
00703     *output = true;
00704   if (exception && fds.revents & POLLPRI)
00705     *exception = true;
00706   if (timedout)
00707     *timedout = false;
00708 
00709   return true;
00710 #else
00711   /*
00712    * We don't have poll(2). We'll have to make do with select(2).
00713    */
00714 
00715   fd_set readfds, writefds, exceptfds;
00716   fd_set *preadfds = 0L, *pwritefds = 0L, *pexceptfds = 0L;
00717 
00718   if (input)
00719     {
00720       preadfds = &readfds;
00721       FD_ZERO(preadfds);
00722       FD_SET(m_sockfd, preadfds);
00723       *input = false;
00724     }
00725   if (output)
00726     {
00727       pwritefds = &writefds;
00728       FD_ZERO(pwritefds);
00729       FD_SET(m_sockfd, pwritefds);
00730       *output = false;
00731     }
00732   if (exception)
00733     {
00734       pexceptfds = &exceptfds;
00735       FD_ZERO(pexceptfds);
00736       FD_SET(m_sockfd, pexceptfds);
00737       *exception = false;
00738     }
00739 
00740   int retval;
00741   if (timeout < 0)
00742     retval = select(m_sockfd + 1, preadfds, pwritefds, pexceptfds, 0L);
00743   else
00744     {
00745       // convert the milliseconds to timeval
00746       struct timeval tv;
00747       tv.tv_sec = timeout / 1000;
00748       tv.tv_usec = timeout % 1000 * 1000;
00749 
00750       retval = select(m_sockfd + 1, preadfds, pwritefds, pexceptfds, &tv);
00751     }
00752 
00753   if (retval == -1)
00754     {
00755       setError(IO_UnspecifiedError, UnknownError);
00756       return false;
00757     }
00758   if (retval == 0)
00759     {
00760       // timeout
00761       if (timedout)
00762     *timedout = true;
00763       return true;
00764     }
00765 
00766   if (input && FD_ISSET(m_sockfd, preadfds))
00767     *input = true;
00768   if (output && FD_ISSET(m_sockfd, pwritefds))
00769     *output = true;
00770   if (exception && FD_ISSET(m_sockfd, pexceptfds))
00771     *exception = true;
00772 
00773   return true;
00774 #endif
00775 }
00776 
00777 bool KSocketDevice::poll(int timeout, bool *timedout)
00778 {
00779   bool input, output, exception;
00780   return poll(&input, &output, &exception, timeout, timedout);
00781 }
00782 
00783 QSocketNotifier* KSocketDevice::createNotifier(QSocketNotifier::Type type) const
00784 {
00785   if (m_sockfd == -1)
00786     return 0L;
00787 
00788   return new QSocketNotifier(m_sockfd, type);
00789 }
00790 
00791 namespace
00792 {
00793   // simple class to avoid pointer stuff
00794   template<class T> class ptr
00795   {
00796     typedef T type;
00797     type* obj;
00798   public:
00799     ptr() : obj(0)
00800     { }
00801 
00802     ptr(const ptr<T>& other) : obj(other.obj)
00803     { }
00804 
00805     ptr(type* _obj) : obj(_obj)
00806     { }
00807 
00808     ~ptr()
00809     { }
00810 
00811     ptr<T>& operator=(const ptr<T>& other)
00812     { obj = other.obj; return *this; }
00813 
00814     ptr<T>& operator=(T* _obj)
00815     { obj = _obj; return  *this; }
00816 
00817     type* operator->() const { return obj; }
00818 
00819     operator T*() const { return obj; }
00820 
00821     bool isNull() const
00822     { return obj == 0; }
00823   };
00824 }
00825 
00826 static KSocketDeviceFactoryBase* defaultImplFactory;
00827 static QMutex defaultImplFactoryMutex;
00828 typedef QMap<int, KSocketDeviceFactoryBase* > factoryMap;
00829 static factoryMap factories;
00830  
00831 KSocketDevice* KSocketDevice::createDefault(KSocketBase* parent)
00832 {
00833   KSocketDevice* device = dynamic_cast<KSocketDevice*>(parent);
00834   if (device != 0L)
00835     return device;
00836 
00837   KSocksSocketDevice::initSocks();
00838 
00839   if (defaultImplFactory)
00840     return defaultImplFactory->create(parent);
00841 
00842   // the really default
00843   return new KSocketDevice(parent);
00844 }
00845 
00846 KSocketDevice* KSocketDevice::createDefault(KSocketBase* parent, int capabilities)
00847 {
00848   KSocketDevice* device = dynamic_cast<KSocketDevice*>(parent);
00849   if (device != 0L)
00850     return device;
00851 
00852   QMutexLocker locker(&defaultImplFactoryMutex);
00853   factoryMap::ConstIterator it = factories.constBegin();
00854   for ( ; it != factories.constEnd(); ++it)
00855     if ((it.key() & capabilities) == capabilities)
00856       // found a match
00857       return it.data()->create(parent);
00858 
00859   return 0L;            // no default
00860 }
00861 
00862 KSocketDeviceFactoryBase*
00863 KSocketDevice::setDefaultImpl(KSocketDeviceFactoryBase* factory)
00864 {
00865   QMutexLocker locker(&defaultImplFactoryMutex);
00866   KSocketDeviceFactoryBase* old = defaultImplFactory;
00867   defaultImplFactory = factory;
00868   return old;
00869 }
00870 
00871 void KSocketDevice::addNewImpl(KSocketDeviceFactoryBase* factory, int capabilities)
00872 {
00873   QMutexLocker locker(&defaultImplFactoryMutex);
00874   if (factories.contains(capabilities))
00875     delete factories[capabilities];
00876   factories.insert(capabilities, factory);
00877 }
00878 
KDE Home | KDE Accessibility Home | Description of Access Keys