File indexing completed on 2023-09-24 04:04:40
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"