File indexing completed on 2024-04-21 14:55:25

0001 /*  -*- C++ -*-
0002  *  Copyright (C) 2003,2005 Thiago Macieira <thiago@kde.org>
0003  *
0004  *
0005  *  Permission is hereby granted, free of charge, to any person obtaining
0006  *  a copy of this software and associated documentation files (the
0007  *  "Software"), to deal in the Software without restriction, including
0008  *  without limitation the rights to use, copy, modify, merge, publish,
0009  *  distribute, sublicense, and/or sell copies of the Software, and to
0010  *  permit persons to whom the Software is furnished to do so, subject to
0011  *  the following conditions:
0012  *
0013  *  The above copyright notice and this permission notice shall be included
0014  *  in all copies or substantial portions of the Software.
0015  *
0016  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
0017  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
0018  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
0019  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
0020  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
0021  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
0022  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
0023  */
0024 
0025 // syssocket.h needs to come before any header that includes k3socketbase.h
0026 #include "syssocket.h"
0027 
0028 #include "k3socketdevice.h" //krazy:exclude=includes (KDE3 compat: not worth fixing)
0029 
0030 #include <config-network.h>
0031 #include <config-kdelibs4support.h>
0032 
0033 #include <QMap>
0034 
0035 #if HAVE_SYS_FILIO_H
0036 # include <sys/filio.h>
0037 #endif
0038 #include <sys/types.h>
0039 #include <sys/socket.h>
0040 #include <sys/time.h>
0041 #include <sys/ioctl.h>
0042 #include <errno.h>
0043 #include <fcntl.h>
0044 #include <netinet/in.h>
0045 #include <netinet/tcp.h>    // WARNING: verify if this is portable
0046 #include <unistd.h>
0047 
0048 #if HAVE_POLL
0049 # include <sys/poll.h>
0050 #else
0051 # if HAVE_SYS_SELECT_H
0052 #  include <sys/select.h>
0053 # endif
0054 #endif
0055 
0056 #ifdef Q_OS_WIN
0057 #include <windows.h>
0058 #endif
0059 
0060 #include <QMutex>
0061 
0062 #include "k3resolver.h"
0063 #include "k3socketaddress.h"
0064 using namespace KNetwork;
0065 
0066 class KNetwork::KSocketDevicePrivate
0067 {
0068 public:
0069     mutable QSocketNotifier *input, *output, *exception;
0070     KSocketAddress local, peer;
0071     int af;
0072     int proto;
0073 
0074     inline KSocketDevicePrivate()
0075     {
0076         input = output = exception = nullptr;
0077         af = proto = 0;
0078     }
0079 };
0080 
0081 KSocketDevice::KSocketDevice(const KSocketBase *parent, QObject *objparent)
0082     : KActiveSocketBase(objparent), m_sockfd(-1),
0083       d(new KSocketDevicePrivate)
0084 {
0085     setSocketDevice(this);
0086     if (parent) {
0087         setSocketOptions(parent->socketOptions());
0088     }
0089 }
0090 
0091 KSocketDevice::KSocketDevice(int fd, OpenMode mode)
0092     : KActiveSocketBase(nullptr), m_sockfd(fd), d(new KSocketDevicePrivate)
0093 {
0094     if (mode) {
0095         mode |= Unbuffered;
0096     }
0097     KActiveSocketBase::open(mode);
0098     setSocketDevice(this);
0099     d->af = localAddress().family();
0100 }
0101 
0102 KSocketDevice::KSocketDevice(QObject *parent)
0103     : KActiveSocketBase(parent), m_sockfd(-1), d(new KSocketDevicePrivate)
0104 {
0105     setSocketDevice(this);
0106 }
0107 
0108 KSocketDevice::KSocketDevice(bool, const KSocketBase *parent)
0109     : KActiveSocketBase(nullptr), m_sockfd(-1), d(new KSocketDevicePrivate)
0110 {
0111     // do not set parent
0112     if (parent) {
0113         setSocketOptions(parent->socketOptions());
0114     }
0115 }
0116 
0117 KSocketDevice::~KSocketDevice()
0118 {
0119     close();          // deletes the notifiers
0120     unsetSocketDevice();      // prevent double deletion
0121     delete d;
0122 }
0123 
0124 int KSocketDevice::socket() const
0125 {
0126     return m_sockfd;
0127 }
0128 
0129 int KSocketDevice::capabilities() const
0130 {
0131     return 0;
0132 }
0133 
0134 bool KSocketDevice::setSocketOptions(int opts)
0135 {
0136     // must call parent
0137     QMutexLocker locker(mutex());
0138     KSocketBase::setSocketOptions(opts);
0139 
0140     if (m_sockfd == -1) {
0141         return true;    // flags are stored
0142     }
0143 
0144 #ifdef Q_OS_WIN
0145     u_long iMode = ((opts & Blocking) == Blocking) ? 0 : 1;
0146     // disable non blocking
0147     if (ioctlsocket(m_sockfd, FIONBIO, &iMode) == SOCKET_ERROR) {
0148         // socket can't made blocking because WSAAsyncSelect/WSAEventSelect (==QSocketNotifier)
0149         // is activated for them
0150         if (WSAGetLastError() == WSAEINVAL) {
0151             return true;
0152         }
0153         qDebug("socket set %s failed %d", iMode ? "nonblocking" : "blocking", GetLastError());
0154         setError(UnknownError);
0155         return false;  // error
0156     }
0157 
0158 #else
0159     {
0160         int fdflags = fcntl(m_sockfd, F_GETFL, 0);
0161         if (fdflags == -1) {
0162             setError(UnknownError);
0163             return false;     // error
0164         }
0165 
0166         if (opts & Blocking) {
0167             fdflags &= ~O_NONBLOCK;
0168         } else {
0169             fdflags |= O_NONBLOCK;
0170         }
0171 
0172         if (fcntl(m_sockfd, F_SETFL, fdflags) == -1) {
0173             setError(UnknownError);
0174             return false;     // error
0175         }
0176     }
0177 #endif
0178 
0179     {
0180         int on = opts & AddressReuseable ? 1 : 0;
0181         if (setsockopt(m_sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) == -1) {
0182             setError(UnknownError);
0183             return false;     // error
0184         }
0185     }
0186 
0187 #if defined(IPV6_V6ONLY) && defined(AF_INET6)
0188     if (d->af == AF_INET6) {
0189         // don't try this on non-IPv6 sockets, or we'll get an error
0190 
0191         int on = opts & IPv6Only ? 1 : 0;
0192         if (setsockopt(m_sockfd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&on, sizeof(on)) == -1) {
0193             setError(UnknownError);
0194             return false;     // error
0195         }
0196     }
0197 #endif
0198 
0199     {
0200         int on = opts & Broadcast ? 1 : 0;
0201         if (setsockopt(m_sockfd, SOL_SOCKET, SO_BROADCAST, (char *)&on, sizeof(on)) == -1) {
0202             setError(UnknownError);
0203             return false;      // error
0204         }
0205     }
0206 
0207     if ((d->proto == IPPROTO_TCP || d->proto == 0) &&
0208             (d->af == AF_INET
0209 #if defined(AF_INET6)
0210              || d->af == AF_INET6
0211 #endif
0212             )) {
0213         int on = opts & NoDelay ? 1 : 0;
0214         if (setsockopt(m_sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&on, sizeof(on)) == -1) {
0215             setError(UnknownError);
0216             return false;      // error
0217         }
0218     }
0219 
0220     return true;          // all went well
0221 }
0222 
0223 void KSocketDevice::close()
0224 {
0225     resetError();
0226     if (m_sockfd != -1) {
0227         delete d->input;
0228         delete d->output;
0229         delete d->exception;
0230 
0231         d->input = d->output = d->exception = nullptr;
0232 #ifdef Q_OS_WIN
0233         ::closesocket(m_sockfd);
0234 #else
0235         d->local.setFamily(AF_UNSPEC);
0236         d->peer.setFamily(AF_UNSPEC);
0237 
0238         ::close(m_sockfd);
0239 #endif
0240     }
0241     setOpenMode(NotOpen);       // closed
0242 
0243     m_sockfd = -1;
0244 }
0245 
0246 bool KSocketDevice::flush()
0247 {
0248     return false;
0249 }
0250 
0251 bool KSocketDevice::create(int family, int type, int protocol)
0252 {
0253     resetError();
0254 
0255     if (m_sockfd != -1) {
0256         // it's already created!
0257         setError(AlreadyCreated);
0258         return false;
0259     }
0260 
0261     // no socket yet; we have to create it
0262     m_sockfd = kde_socket(family, type, protocol);
0263 
0264     if (m_sockfd == -1) {
0265         setError(NotSupported);
0266         return false;
0267     }
0268 
0269     d->af = family;
0270     d->proto = protocol;
0271     setSocketOptions(socketOptions());
0272     setOpenMode(Unbuffered);  // there's no "Open" flag
0273     return true;      // successfully created
0274 }
0275 
0276 bool KSocketDevice::create(const KResolverEntry &address)
0277 {
0278     return create(address.family(), address.socketType(), address.protocol());
0279 }
0280 
0281 bool KSocketDevice::bind(const KResolverEntry &address)
0282 {
0283     resetError();
0284 
0285     if (m_sockfd == -1 && !create(address)) {
0286         return false;    // failed creating
0287     }
0288 
0289     // we have a socket, so try and bind
0290     if (kde_bind(m_sockfd, address.address(), address.length()) == -1) {
0291         if (errno == EADDRINUSE) {
0292             setError(AddressInUse);
0293             return false;
0294         } else if (errno == EINVAL) {
0295             setError(AlreadyBound);
0296         } else {
0297 #ifdef Q_OS_WIN
0298             qDebug(" bind failed: %s ", address.address().toString().toLatin1().constData());
0299 #endif
0300             // assume the address is the cause
0301             setError(NotSupported);
0302             return false;
0303         }
0304     }
0305 
0306     return true;
0307 }
0308 
0309 bool KSocketDevice::listen(int backlog)
0310 {
0311     if (m_sockfd != -1) {
0312         if (kde_listen(m_sockfd, backlog) == -1) {
0313             setError(NotSupported);
0314             return false;
0315         }
0316 
0317         resetError();
0318         setOpenMode(QIODevice::Unbuffered | QIODevice::ReadWrite);
0319         return true;
0320     }
0321 
0322     // we don't have a socket
0323     // can't listen
0324     setError(NotCreated);
0325     return false;
0326 }
0327 
0328 bool KSocketDevice::connect(const KResolverEntry &address, OpenMode mode)
0329 {
0330     resetError();
0331 
0332     if (m_sockfd == -1 && !create(address)) {
0333         return false;    // failed creating!
0334     }
0335 
0336     if (kde_connect(m_sockfd, address.address(), address.length()) == -1) {
0337         if (errno == EISCONN) {
0338             KActiveSocketBase::open(Unbuffered | mode);
0339             return true;      // we're already connected
0340         } else if (errno == EALREADY || errno == EINPROGRESS) {
0341             KActiveSocketBase::open(Unbuffered | mode);
0342             setError(InProgress);
0343             return true;
0344         } else if (errno == ECONNREFUSED) {
0345             setError(ConnectionRefused);
0346         } else if (errno == ENETDOWN || errno == ENETUNREACH ||
0347                    errno == ENETRESET || errno == ECONNABORTED ||
0348                    errno == ECONNRESET || errno == EHOSTDOWN ||
0349                    errno == EHOSTUNREACH) {
0350             setError(NetFailure);
0351         } else {
0352             setError(NotSupported);
0353         }
0354 
0355         return false;
0356     }
0357 
0358     KActiveSocketBase::open(Unbuffered | mode);
0359     return true;          // all is well
0360 }
0361 
0362 KSocketDevice *KSocketDevice::accept()
0363 {
0364     if (m_sockfd == -1) {
0365         // can't accept without a socket
0366         setError(NotCreated);
0367         return nullptr;
0368     }
0369 
0370     struct sockaddr sa;
0371     socklen_t len = sizeof(sa);
0372     int newfd = kde_accept(m_sockfd, &sa, &len);
0373     if (newfd == -1) {
0374         if (errno == EAGAIN || errno == EWOULDBLOCK) {
0375             setError(WouldBlock);
0376         } else {
0377             setError(UnknownError);
0378         }
0379         return nullptr;
0380     }
0381 
0382     return new KSocketDevice(newfd);
0383 }
0384 
0385 bool KSocketDevice::disconnect()
0386 {
0387     resetError();
0388 
0389     if (m_sockfd == -1) {
0390         return false;    // can't create
0391     }
0392 
0393     KSocketAddress address;
0394     address.setFamily(AF_UNSPEC);
0395     if (kde_connect(m_sockfd, address.address(), address.length()) == -1) {
0396         if (errno == EALREADY || errno == EINPROGRESS) {
0397             setError(InProgress);
0398             return false;
0399         } else if (errno == ECONNREFUSED) {
0400             setError(ConnectionRefused);
0401         } else if (errno == ENETDOWN || errno == ENETUNREACH ||
0402                    errno == ENETRESET || errno == ECONNABORTED ||
0403                    errno == ECONNRESET || errno == EHOSTDOWN ||
0404                    errno == EHOSTUNREACH) {
0405             setError(NetFailure);
0406         } else {
0407             setError(NotSupported);
0408         }
0409 
0410         return false;
0411     }
0412 
0413     setOpenMode(QIODevice::Unbuffered | QIODevice::ReadWrite);
0414     return true;          // all is well
0415 }
0416 
0417 qint64 KSocketDevice::bytesAvailable() const
0418 {
0419     if (m_sockfd == -1) {
0420         return -1;    // there's nothing to read in a closed socket
0421     }
0422 
0423     int nchars;
0424     if (kde_ioctl(m_sockfd, FIONREAD, &nchars) == -1) {
0425         return -1;    // error!
0426     }
0427 
0428     return nchars;
0429 }
0430 
0431 qint64 KSocketDevice::waitForMore(int msecs, bool *timeout)
0432 {
0433     if (m_sockfd == -1) {
0434         return -1;    // there won't ever be anything to read...
0435     }
0436 
0437     bool input;
0438     if (!poll(&input, nullptr, nullptr, msecs, timeout)) {
0439         return -1;    // failed polling
0440     }
0441 
0442     return bytesAvailable();
0443 }
0444 
0445 static int do_read_common(int sockfd, char *data, qint64 maxlen, KSocketAddress *from, ssize_t &retval, bool peek = false)
0446 {
0447     socklen_t len;
0448     if (from) {
0449         from->setLength(len = 128); // arbitrary length
0450         retval = ::recvfrom(sockfd, data, maxlen, peek ? MSG_PEEK : 0, from->address(), &len);
0451     } else {
0452         retval = ::recvfrom(sockfd, data, maxlen, peek ? MSG_PEEK : 0, nullptr, nullptr);
0453     }
0454 
0455     if (retval == -1) {
0456 #ifdef Q_OS_WIN
0457         if (WSAGetLastError() == WSAEWOULDBLOCK) {
0458             return KSocketDevice::WouldBlock;
0459         } else
0460 #endif
0461             if (errno == EAGAIN || errno == EWOULDBLOCK) {
0462                 return KSocketDevice::WouldBlock;
0463             } else {
0464                 return KSocketDevice::UnknownError;
0465             }
0466     }
0467     if (retval == 0) {
0468         return KSocketDevice::RemotelyDisconnected;
0469     }
0470 
0471     if (from) {
0472         from->setLength(len);
0473     }
0474     return 0;
0475 }
0476 
0477 qint64 KSocketDevice::readData(char *data, qint64 maxlen, KSocketAddress *from)
0478 {
0479     resetError();
0480     if (m_sockfd == -1) {
0481         return -1;    // nothing to do here
0482     }
0483 
0484     if (data == nullptr || maxlen == 0) {
0485         return 0;    // user doesn't want to read
0486     }
0487 
0488     ssize_t retval;
0489     int err = do_read_common(m_sockfd, data, maxlen, from, retval);
0490 
0491     if (err) {
0492         setError(static_cast<SocketError>(err));
0493         return -1;
0494     }
0495 
0496     return retval;
0497 }
0498 
0499 qint64 KSocketDevice::peekData(char *data, qint64 maxlen, KSocketAddress *from)
0500 {
0501     resetError();
0502     if (m_sockfd == -1) {
0503         return -1;    // nothing to do here
0504     }
0505 
0506     if (data == nullptr || maxlen == 0) {
0507         return 0;    // user doesn't want to read
0508     }
0509 
0510     ssize_t retval;
0511     int err = do_read_common(m_sockfd, data, maxlen, from, retval, true);
0512 
0513     if (err) {
0514         setError(static_cast<SocketError>(err));
0515         return -1;
0516     }
0517 
0518     return retval;
0519 }
0520 
0521 qint64 KSocketDevice::writeData(const char *data, qint64 len, const KSocketAddress *to)
0522 {
0523     resetError();
0524     if (m_sockfd == -1) {
0525         return -1;    // can't write to unopen socket
0526     }
0527 
0528     if (data == nullptr || len == 0) {
0529         return 0;    // nothing to be written
0530     }
0531 
0532     ssize_t retval;
0533     if (to != nullptr) {
0534         retval = ::sendto(m_sockfd, data, len, 0, to->address(), to->length());
0535     } else
0536 #ifdef Q_OS_WIN
0537         retval = ::send(m_sockfd, data, len, 0);
0538 #else
0539         retval = ::write(m_sockfd, data, len);
0540 #endif
0541     if (retval == -1) {
0542         if (errno == EAGAIN || errno == EWOULDBLOCK) {
0543             setError(WouldBlock);
0544         } else {
0545             setError(UnknownError);
0546         }
0547         return -1;        // nothing written
0548     } else if (retval == 0) {
0549         setError(RemotelyDisconnected);
0550     }
0551 
0552     return retval;
0553 }
0554 
0555 KSocketAddress KSocketDevice::localAddress() const
0556 {
0557     if (m_sockfd == -1) {
0558         return KSocketAddress();    // not open, empty value
0559     }
0560 
0561     if (d->local.family() != AF_UNSPEC) {
0562         return d->local;
0563     }
0564 
0565     socklen_t len;
0566     KSocketAddress localAddress;
0567     localAddress.setLength(len = 32); // arbitrary value
0568     if (kde_getsockname(m_sockfd, localAddress.address(), &len) == -1)
0569         // error!
0570     {
0571         return d->local = KSocketAddress();
0572     }
0573 
0574 #if HAVE_STRUCT_SOCKADDR_SA_LEN
0575     len = localAddress.address()->sa_len;
0576 #endif
0577 
0578     if (len <= localAddress.length()) {
0579         // it has fit already
0580         localAddress.setLength(len);
0581         return d->local = localAddress;
0582     }
0583 
0584     // no, the socket address is actually larger than we had anticipated
0585     // call again
0586     localAddress.setLength(len);
0587     if (kde_getsockname(m_sockfd, localAddress.address(), &len) == -1)
0588         // error!
0589     {
0590         return d->local = KSocketAddress();
0591     }
0592 
0593     return d->local = localAddress;
0594 }
0595 
0596 KSocketAddress KSocketDevice::peerAddress() const
0597 {
0598     if (m_sockfd == -1) {
0599         return KSocketAddress();    // not open, empty value
0600     }
0601 
0602     if (d->peer.family() != AF_UNSPEC) {
0603         return d->peer;
0604     }
0605 
0606     socklen_t len;
0607     KSocketAddress peerAddress;
0608     peerAddress.setLength(len = 32);  // arbitrary value
0609     if (kde_getpeername(m_sockfd, peerAddress.address(), &len) == -1)
0610         // error!
0611     {
0612         return d->peer = KSocketAddress();
0613     }
0614 
0615 #if HAVE_STRUCT_SOCKADDR_SA_LEN
0616     len = peerAddress.address()->sa_len;
0617 #endif
0618 
0619     if (len <= peerAddress.length()) {
0620         // it has fit already
0621         peerAddress.setLength(len);
0622         return d->peer = peerAddress;
0623     }
0624 
0625     // no, the socket address is actually larger than we had anticipated
0626     // call again
0627     peerAddress.setLength(len);
0628     if (kde_getpeername(m_sockfd, peerAddress.address(), &len) == -1)
0629         // error!
0630     {
0631         return d->peer = KSocketAddress();
0632     }
0633 
0634     return d->peer = peerAddress;
0635 }
0636 
0637 KSocketAddress KSocketDevice::externalAddress() const
0638 {
0639     // for normal sockets, the externally visible address is the same
0640     // as the local address
0641     return localAddress();
0642 }
0643 
0644 QSocketNotifier *KSocketDevice::readNotifier() const
0645 {
0646     if (d->input) {
0647         return d->input;
0648     }
0649 
0650     QMutexLocker locker(mutex());
0651     if (d->input) {
0652         return d->input;
0653     }
0654 
0655     if (m_sockfd == -1) {
0656         // socket doesn't exist; can't create notifier
0657         return nullptr;
0658     }
0659 
0660     return d->input = createNotifier(QSocketNotifier::Read);
0661 }
0662 
0663 QSocketNotifier *KSocketDevice::writeNotifier() const
0664 {
0665     if (d->output) {
0666         return d->output;
0667     }
0668 
0669     QMutexLocker locker(mutex());
0670     if (d->output) {
0671         return d->output;
0672     }
0673 
0674     if (m_sockfd == -1) {
0675         // socket doesn't exist; can't create notifier
0676         return nullptr;
0677     }
0678 
0679     return d->output = createNotifier(QSocketNotifier::Write);
0680 }
0681 
0682 QSocketNotifier *KSocketDevice::exceptionNotifier() const
0683 {
0684     if (d->exception) {
0685         return d->exception;
0686     }
0687 
0688     QMutexLocker locker(mutex());
0689     if (d->exception) {
0690         return d->exception;
0691     }
0692 
0693     if (m_sockfd == -1) {
0694         // socket doesn't exist; can't create notifier
0695         return nullptr;
0696     }
0697 
0698     return d->exception = createNotifier(QSocketNotifier::Exception);
0699 }
0700 
0701 bool KSocketDevice::poll(bool *input, bool *output, bool *exception,
0702                          int timeout, bool *timedout)
0703 {
0704     if (m_sockfd == -1) {
0705         setError(NotCreated);
0706         return false;
0707     }
0708 
0709     resetError();
0710 #if HAVE_POLL
0711     struct pollfd fds;
0712     fds.fd = m_sockfd;
0713     fds.events = 0;
0714 
0715     if (input) {
0716         fds.events |= POLLIN;
0717         *input = false;
0718     }
0719     if (output) {
0720         fds.events |= POLLOUT;
0721         *output = false;
0722     }
0723     if (exception) {
0724         fds.events |= POLLPRI;
0725         *exception = false;
0726     }
0727 
0728     int retval = ::poll(&fds, 1, timeout);
0729     if (retval == -1) {
0730         setError(UnknownError);
0731         return false;
0732     }
0733     if (retval == 0) {
0734         // timeout
0735         if (timedout) {
0736             *timedout = true;
0737         }
0738         return true;
0739     }
0740 
0741     if (input && fds.revents & POLLIN) {
0742         *input = true;
0743     }
0744     if (output && fds.revents & POLLOUT) {
0745         *output = true;
0746     }
0747     if (exception && fds.revents & POLLPRI) {
0748         *exception = true;
0749     }
0750     if (timedout) {
0751         *timedout = false;
0752     }
0753 
0754     return true;
0755 #else
0756     /*
0757      * We don't have poll(2). We'll have to make do with select(2).
0758      */
0759 
0760     fd_set readfds, writefds, exceptfds;
0761     fd_set *preadfds = 0L, *pwritefds = 0L, *pexceptfds = 0L;
0762 
0763     if (input) {
0764         preadfds = &readfds;
0765         FD_ZERO(preadfds);
0766         FD_SET(m_sockfd, preadfds);
0767         *input = false;
0768     }
0769     if (output) {
0770         pwritefds = &writefds;
0771         FD_ZERO(pwritefds);
0772         FD_SET(m_sockfd, pwritefds);
0773         *output = false;
0774     }
0775     if (exception) {
0776         pexceptfds = &exceptfds;
0777         FD_ZERO(pexceptfds);
0778         FD_SET(m_sockfd, pexceptfds);
0779         *exception = false;
0780     }
0781 
0782     int retval;
0783     if (timeout < 0) {
0784         retval = select(m_sockfd + 1, preadfds, pwritefds, pexceptfds, 0L);
0785     } else {
0786         // convert the milliseconds to timeval
0787         struct timeval tv;
0788         tv.tv_sec = timeout / 1000;
0789         tv.tv_usec = timeout % 1000 * 1000;
0790 
0791         retval = select(m_sockfd + 1, preadfds, pwritefds, pexceptfds, &tv);
0792     }
0793 
0794     if (retval == -1) {
0795         setError(UnknownError);
0796         return false;
0797     }
0798     if (retval == 0) {
0799         // timeout
0800         if (timedout) {
0801             *timedout = true;
0802         }
0803         return true;
0804     }
0805 
0806     if (input && FD_ISSET(m_sockfd, preadfds)) {
0807         *input = true;
0808     }
0809     if (output && FD_ISSET(m_sockfd, pwritefds)) {
0810         *output = true;
0811     }
0812     if (exception && FD_ISSET(m_sockfd, pexceptfds)) {
0813         *exception = true;
0814     }
0815 
0816     return true;
0817 #endif
0818 }
0819 
0820 bool KSocketDevice::poll(int timeout, bool *timedout)
0821 {
0822     bool input, output, exception;
0823     return poll(&input, &output, &exception, timeout, timedout);
0824 }
0825 
0826 QSocketNotifier *KSocketDevice::createNotifier(QSocketNotifier::Type type) const
0827 {
0828     if (m_sockfd == -1) {
0829         return nullptr;
0830     }
0831 
0832     return new QSocketNotifier(m_sockfd, type);
0833 }
0834 
0835 namespace
0836 {
0837 // simple class to avoid pointer stuff
0838 template<class T> class ptr
0839 {
0840     typedef T type;
0841     type *obj;
0842 public:
0843     ptr() : obj(0)
0844     { }
0845 
0846     ptr(const ptr<T> &other) : obj(other.obj)
0847     { }
0848 
0849     ptr(type *_obj) : obj(_obj)
0850     { }
0851 
0852     ~ptr()
0853     { }
0854 
0855     ptr<T> &operator=(const ptr<T> &other)
0856     {
0857         obj = other.obj;
0858         return *this;
0859     }
0860 
0861     ptr<T> &operator=(T *_obj)
0862     {
0863         obj = _obj;
0864         return  *this;
0865     }
0866 
0867     type *operator->() const
0868     {
0869         return obj;
0870     }
0871 
0872     operator T *() const
0873     {
0874         return obj;
0875     }
0876 
0877     bool isNull() const
0878     {
0879         return obj == 0;
0880     }
0881 };
0882 }
0883 
0884 static KSocketDeviceFactoryBase *defaultImplFactory;
0885 static QMutex defaultImplFactoryMutex;
0886 typedef QMap<int, KSocketDeviceFactoryBase * > factoryMap;
0887 static factoryMap factories;
0888 
0889 KSocketDevice *KSocketDevice::createDefault(KSocketBase *parent)
0890 {
0891     KSocketDevice *device = dynamic_cast<KSocketDevice *>(parent);
0892     if (device != nullptr) {
0893         return device;
0894     }
0895 
0896     if (defaultImplFactory) {
0897         return defaultImplFactory->create(parent);
0898     }
0899 
0900     // the really default
0901     return new KSocketDevice(parent);
0902 }
0903 
0904 KSocketDevice *KSocketDevice::createDefault(KSocketBase *parent, int capabilities)
0905 {
0906     KSocketDevice *device = dynamic_cast<KSocketDevice *>(parent);
0907     if (device != nullptr) {
0908         return device;
0909     }
0910 
0911     QMutexLocker locker(&defaultImplFactoryMutex);
0912     factoryMap::ConstIterator it = factories.constBegin();
0913     for (; it != factories.constEnd(); ++it)
0914         if ((it.key() & capabilities) == capabilities)
0915             // found a match
0916         {
0917             return it.value()->create(parent);
0918         }
0919 
0920     return nullptr;            // no default
0921 }
0922 
0923 KSocketDeviceFactoryBase *
0924 KSocketDevice::setDefaultImpl(KSocketDeviceFactoryBase *factory)
0925 {
0926     QMutexLocker locker(&defaultImplFactoryMutex);
0927     KSocketDeviceFactoryBase *old = defaultImplFactory;
0928     defaultImplFactory = factory;
0929     return old;
0930 }
0931 
0932 void KSocketDevice::addNewImpl(KSocketDeviceFactoryBase *factory, int capabilities)
0933 {
0934     QMutexLocker locker(&defaultImplFactoryMutex);
0935     if (factories.contains(capabilities)) {
0936         delete factories[capabilities];
0937     }
0938     factories.insert(capabilities, factory);
0939 }
0940