File indexing completed on 2024-03-24 15:27:09

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 #include "k3socketbase.h"
0026 
0027 #include <config-network.h>
0028 #include <QMutex>
0029 #include <klocalizedstring.h>
0030 
0031 #include "k3socketdevice.h"
0032 
0033 #ifdef Q_OS_WIN
0034 #include <winsock2.h>
0035 
0036 void KNetwork_initSocket()
0037 {
0038     static bool hasStarted = false;
0039     if (!hasStarted) {
0040         WSADATA wsaData;
0041         WORD wVersionRequested = MAKEWORD(2, 2);
0042         WSAStartup(wVersionRequested, &wsaData);
0043         hasStarted = true;
0044     }
0045 }
0046 #endif
0047 
0048 using namespace KNetwork;
0049 
0050 class KNetwork::KSocketBasePrivate
0051 {
0052 public:
0053     int socketOptions;
0054     int socketError;
0055     int capabilities;
0056 
0057     mutable KSocketDevice *device;
0058 
0059     QMutex mutex;
0060 
0061     KSocketBasePrivate()
0062         : mutex(QMutex::Recursive)      // create recursive
0063     { }
0064 };
0065 
0066 KSocketBase::KSocketBase()
0067     : d(new KSocketBasePrivate)
0068 {
0069     d->socketOptions = Blocking;
0070     d->socketError = 0;
0071     d->device = nullptr;
0072     d->capabilities = 0;
0073 #ifdef Q_OS_WIN
0074     KNetwork_initSocket();
0075 #endif
0076 }
0077 
0078 KSocketBase::~KSocketBase()
0079 {
0080     delete d->device;
0081     delete d;
0082 }
0083 
0084 bool KSocketBase::setSocketOptions(int opts)
0085 {
0086     d->socketOptions = opts;
0087     return true;
0088 }
0089 
0090 int KSocketBase::socketOptions() const
0091 {
0092     return d->socketOptions;
0093 }
0094 
0095 bool KSocketBase::setBlocking(bool enable)
0096 {
0097     return setSocketOptions((socketOptions() & ~Blocking) | (enable ? Blocking : 0));
0098 }
0099 
0100 bool KSocketBase::blocking() const
0101 {
0102     return socketOptions() & Blocking;
0103 }
0104 
0105 bool KSocketBase::setAddressReuseable(bool enable)
0106 {
0107     return setSocketOptions((socketOptions() & ~AddressReuseable) | (enable ? AddressReuseable : 0));
0108 }
0109 
0110 bool KSocketBase::addressReuseable() const
0111 {
0112     return socketOptions() & AddressReuseable;
0113 }
0114 
0115 bool KSocketBase::setIPv6Only(bool enable)
0116 {
0117     return setSocketOptions((socketOptions() & ~IPv6Only) | (enable ? IPv6Only : 0));
0118 }
0119 
0120 bool KSocketBase::isIPv6Only() const
0121 {
0122     return socketOptions() & IPv6Only;
0123 }
0124 
0125 bool KSocketBase::setBroadcast(bool enable)
0126 {
0127     return setSocketOptions((socketOptions() & ~Broadcast) | (enable ? Broadcast : 0));
0128 }
0129 
0130 bool KSocketBase::broadcast() const
0131 {
0132     return socketOptions() & Broadcast;
0133 }
0134 
0135 bool KSocketBase::setNoDelay(bool enable)
0136 {
0137     return setSocketOptions((socketOptions() & ~NoDelay) | (enable ? NoDelay : 0));
0138 }
0139 
0140 bool KSocketBase::noDelay() const
0141 {
0142     return socketOptions() & NoDelay;
0143 }
0144 
0145 KSocketDevice *KSocketBase::socketDevice() const
0146 {
0147     if (d->device) {
0148         return d->device;
0149     }
0150 
0151     // it doesn't exist, so create it
0152     QMutexLocker locker(mutex());
0153     if (d->device) {
0154         return d->device;
0155     }
0156 
0157     KSocketBase *that = const_cast<KSocketBase *>(this);
0158     KSocketDevice *dev = nullptr;
0159     if (d->capabilities) {
0160         dev = KSocketDevice::createDefault(that, d->capabilities);
0161     }
0162     if (!dev) {
0163         dev = KSocketDevice::createDefault(that);
0164     }
0165     that->setSocketDevice(dev);
0166     return d->device;
0167 }
0168 
0169 void KSocketBase::setSocketDevice(KSocketDevice *device)
0170 {
0171     QMutexLocker locker(mutex());
0172     if (d->device == nullptr) {
0173         d->device = device;
0174     }
0175 }
0176 
0177 int KSocketBase::setRequestedCapabilities(int add, int remove)
0178 {
0179     d->capabilities |= add;
0180     d->capabilities &= ~remove;
0181     return d->capabilities;
0182 }
0183 
0184 bool KSocketBase::hasDevice() const
0185 {
0186     return d->device != nullptr;
0187 }
0188 
0189 void KSocketBase::setError(SocketError error)
0190 {
0191     d->socketError = error;
0192 }
0193 
0194 void KSocketBase::resetError()
0195 {
0196     d->socketError = NoError;
0197 }
0198 
0199 KSocketBase::SocketError KSocketBase::error() const
0200 {
0201     return static_cast<KSocketBase::SocketError>(d->socketError);
0202 }
0203 
0204 QString KSocketBase::errorString() const
0205 {
0206     return errorString(error());
0207 }
0208 
0209 // static
0210 QString KSocketBase::errorString(KSocketBase::SocketError code)
0211 {
0212     QString reason;
0213     switch (code) {
0214     case NoError:
0215         reason = i18nc("Socket error code NoError", "no error");
0216         break;
0217 
0218     case LookupFailure:
0219         reason = i18nc("Socket error code LookupFailure",
0220                        "name lookup has failed");
0221         break;
0222 
0223     case AddressInUse:
0224         reason = i18nc("Socket error code AddressInUse",
0225                        "address already in use");
0226         break;
0227 
0228     case AlreadyBound:
0229         reason = i18nc("Socket error code AlreadyBound",
0230                        "socket is already bound");
0231         break;
0232 
0233     case AlreadyCreated:
0234         reason = i18nc("Socket error code AlreadyCreated",
0235                        "socket is already created");
0236         break;
0237 
0238     case NotBound:
0239         reason = i18nc("Socket error code NotBound",
0240                        "socket is not bound");
0241         break;
0242 
0243     case NotCreated:
0244         reason = i18nc("Socket error code NotCreated",
0245                        "socket has not been created");
0246         break;
0247 
0248     case WouldBlock:
0249         reason = i18nc("Socket error code WouldBlock",
0250                        "operation would block");
0251         break;
0252 
0253     case ConnectionRefused:
0254         reason = i18nc("Socket error code ConnectionRefused",
0255                        "connection actively refused");
0256         break;
0257 
0258     case ConnectionTimedOut:
0259         reason = i18nc("Socket error code ConnectionTimedOut",
0260                        "connection timed out");
0261         break;
0262 
0263     case InProgress:
0264         reason = i18nc("Socket error code InProgress",
0265                        "operation is already in progress");
0266         break;
0267 
0268     case NetFailure:
0269         reason = i18nc("Socket error code NetFailure",
0270                        "network failure occurred");
0271         break;
0272 
0273     case NotSupported:
0274         reason = i18nc("Socket error code NotSupported",
0275                        "operation is not supported");
0276         break;
0277 
0278     case Timeout:
0279         reason = i18nc("Socket error code Timeout",
0280                        "timed operation timed out");
0281         break;
0282 
0283     case UnknownError:
0284         reason = i18nc("Socket error code UnknownError",
0285                        "an unknown/unexpected error has happened");
0286         break;
0287 
0288     case RemotelyDisconnected:
0289         reason = i18nc("Socket error code RemotelyDisconnected",
0290                        "remote host closed connection");
0291         break;
0292 
0293     default:
0294         reason.clear();
0295         break;
0296     }
0297 
0298     return reason;
0299 }
0300 
0301 // static
0302 bool KSocketBase::isFatalError(int code)
0303 {
0304     switch (code) {
0305     case WouldBlock:
0306     case InProgress:
0307     case NoError:
0308     case RemotelyDisconnected:
0309         return false;
0310     }
0311 
0312     return true;
0313 }
0314 
0315 void KSocketBase::unsetSocketDevice()
0316 {
0317     d->device = nullptr;
0318 }
0319 
0320 QMutex *KSocketBase::mutex() const
0321 {
0322     return &d->mutex;
0323 }
0324 
0325 KActiveSocketBase::KActiveSocketBase(QObject *parent)
0326     : QIODevice(parent)
0327 {
0328 }
0329 
0330 KActiveSocketBase::~KActiveSocketBase()
0331 {
0332 }
0333 
0334 QString KActiveSocketBase::errorString() const
0335 {
0336     return QIODevice::errorString();
0337 }
0338 
0339 bool KActiveSocketBase::open(OpenMode mode)
0340 {
0341     QIODevice::open(mode);
0342     if (mode != QIODevice::NotOpen) {
0343         QIODevice::seek(0);    // clear unget buffers
0344     }
0345     return true;
0346 }
0347 
0348 void KActiveSocketBase::setSocketDevice(KSocketDevice *dev)
0349 {
0350     KSocketBase::setSocketDevice(dev);
0351     KActiveSocketBase::open(dev->openMode());
0352 }
0353 
0354 bool KActiveSocketBase::isSequential() const
0355 {
0356     return true;
0357 }
0358 
0359 qint64 KActiveSocketBase::size() const
0360 {
0361     return 0;
0362 }
0363 
0364 qint64 KActiveSocketBase::pos() const
0365 {
0366     return 0;
0367 }
0368 
0369 bool KActiveSocketBase::seek(qint64)
0370 {
0371     return false;
0372 }
0373 
0374 bool KActiveSocketBase::atEnd() const
0375 {
0376     return true;
0377 }
0378 
0379 qint64 KActiveSocketBase::read(char *data, qint64 maxlen)
0380 {
0381     return QIODevice::read(data, maxlen);
0382 }
0383 
0384 QByteArray KActiveSocketBase::read(qint64 len)
0385 {
0386     return QIODevice::read(len);
0387 }
0388 
0389 qint64 KActiveSocketBase::read(char *data, qint64 len, KSocketAddress &from)
0390 {
0391     // FIXME TODO: implement unget buffers
0392     return readData(data, len, &from);
0393 }
0394 
0395 qint64 KActiveSocketBase::peek(char *data, qint64 len)
0396 {
0397     return peekData(data, len, nullptr);
0398 }
0399 
0400 qint64 KActiveSocketBase::peek(char *data, qint64 len, KSocketAddress &from)
0401 {
0402     return peekData(data, len, &from);
0403 }
0404 
0405 qint64 KActiveSocketBase::write(const char *data, qint64 len)
0406 {
0407     return QIODevice::write(data, len);
0408 }
0409 
0410 qint64 KActiveSocketBase::write(const QByteArray &data)
0411 {
0412     return QIODevice::write(data);
0413 }
0414 
0415 qint64 KActiveSocketBase::write(const char *data, qint64 len,
0416                                 const KSocketAddress &to)
0417 {
0418     return writeData(data, len, &to);
0419 }
0420 
0421 void KActiveSocketBase::ungetChar(char)
0422 {
0423     return;
0424 }
0425 
0426 qint64 KActiveSocketBase::readData(char *data, qint64 len)
0427 {
0428     return readData(data, len, nullptr);
0429 }
0430 
0431 qint64 KActiveSocketBase::writeData(const char *data, qint64 len)
0432 {
0433     return writeData(data, len, nullptr);
0434 }
0435 
0436 void KActiveSocketBase::setError(SocketError error)
0437 {
0438     KSocketBase::setError(error);
0439     setErrorString(KSocketBase::errorString());
0440 }
0441 
0442 void KActiveSocketBase::resetError()
0443 {
0444     KSocketBase::setError(NoError);
0445     setErrorString(QString());
0446 }
0447 
0448 KPassiveSocketBase::KPassiveSocketBase()
0449 {
0450 }
0451 
0452 KPassiveSocketBase::~KPassiveSocketBase()
0453 {
0454 }
0455 
0456 #include "moc_k3socketbase.cpp"