kdecore Library: ksocketdevice.cpp Source File (kdecore Library)

| # kdecore Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# 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

This file is part of the documentation for kdecore Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:18:11 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003