kbufferedsocket.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <config.h>
00026
00027 #include <qmutex.h>
00028 #include <qtimer.h>
00029
00030 #include "ksocketdevice.h"
00031 #include "ksocketaddress.h"
00032 #include "ksocketbuffer_p.h"
00033 #include "kbufferedsocket.h"
00034
00035 using namespace KNetwork;
00036 using namespace KNetwork::Internal;
00037
00038 class KNetwork::KBufferedSocketPrivate
00039 {
00040 public:
00041 mutable KSocketBuffer *input, *output;
00042
00043 KBufferedSocketPrivate()
00044 {
00045 input = 0L;
00046 output = 0L;
00047 }
00048 };
00049
00050 KBufferedSocket::KBufferedSocket(const QString& host, const QString& service,
00051 QObject *parent, const char *name)
00052 : KStreamSocket(host, service, parent, name),
00053 d(new KBufferedSocketPrivate)
00054 {
00055 setInputBuffering(true);
00056 setOutputBuffering(true);
00057 }
00058
00059 KBufferedSocket::~KBufferedSocket()
00060 {
00061 closeNow();
00062 delete d->input;
00063 delete d->output;
00064 delete d;
00065 }
00066
00067 void KBufferedSocket::setSocketDevice(KSocketDevice* device)
00068 {
00069 KStreamSocket::setSocketDevice(device);
00070 device->setBlocking(false);
00071 }
00072
00073 bool KBufferedSocket::setSocketOptions(int opts)
00074 {
00075 if (opts == Blocking)
00076 return false;
00077
00078 opts &= ~Blocking;
00079 return KStreamSocket::setSocketOptions(opts);
00080 }
00081
00082 void KBufferedSocket::close()
00083 {
00084 if (!d->output || d->output->isEmpty())
00085 closeNow();
00086 else
00087 {
00088 setState(Closing);
00089 QSocketNotifier *n = socketDevice()->readNotifier();
00090 if (n)
00091 n->setEnabled(false);
00092 emit stateChanged(Closing);
00093 }
00094 }
00095
00096 Q_LONG KBufferedSocket::bytesAvailable() const
00097 {
00098 if (!d->input)
00099 return KStreamSocket::bytesAvailable();
00100
00101 return d->input->length();
00102 }
00103
00104 Q_LONG KBufferedSocket::waitForMore(int msecs, bool *timeout)
00105 {
00106 Q_LONG retval = KStreamSocket::waitForMore(msecs, timeout);
00107 if (d->input)
00108 {
00109 resetError();
00110 slotReadActivity();
00111 return bytesAvailable();
00112 }
00113 return retval;
00114 }
00115
00116 Q_LONG KBufferedSocket::readBlock(char *data, Q_ULONG maxlen)
00117 {
00118 if (d->input)
00119 {
00120 if (d->input->isEmpty())
00121 {
00122 setError(IO_ReadError, WouldBlock);
00123 emit gotError(WouldBlock);
00124 return -1;
00125 }
00126 resetError();
00127 return d->input->consumeBuffer(data, maxlen);
00128 }
00129 return KStreamSocket::readBlock(data, maxlen);
00130 }
00131
00132 Q_LONG KBufferedSocket::readBlock(char *data, Q_ULONG maxlen, KSocketAddress& from)
00133 {
00134 from = peerAddress();
00135 return readBlock(data, maxlen);
00136 }
00137
00138 Q_LONG KBufferedSocket::peekBlock(char *data, Q_ULONG maxlen)
00139 {
00140 if (d->input)
00141 {
00142 if (d->input->isEmpty())
00143 {
00144 setError(IO_ReadError, WouldBlock);
00145 emit gotError(WouldBlock);
00146 return -1;
00147 }
00148 resetError();
00149 return d->input->consumeBuffer(data, maxlen, false);
00150 }
00151 return KStreamSocket::peekBlock(data, maxlen);
00152 }
00153
00154 Q_LONG KBufferedSocket::peekBlock(char *data, Q_ULONG maxlen, KSocketAddress& from)
00155 {
00156 from = peerAddress();
00157 return peekBlock(data, maxlen);
00158 }
00159
00160 Q_LONG KBufferedSocket::writeBlock(const char *data, Q_ULONG len)
00161 {
00162 if (state() != Connected)
00163 {
00164
00165 setError(IO_WriteError, NotConnected);
00166 return -1;
00167 }
00168
00169 if (d->output)
00170 {
00171 if (d->output->isFull())
00172 {
00173 setError(IO_WriteError, WouldBlock);
00174 emit gotError(WouldBlock);
00175 return -1;
00176 }
00177 resetError();
00178
00179
00180 QSocketNotifier *n = socketDevice()->writeNotifier();
00181 if (n)
00182 n->setEnabled(true);
00183
00184 return d->output->feedBuffer(data, len);
00185 }
00186
00187 return KStreamSocket::writeBlock(data, len);
00188 }
00189
00190 Q_LONG KBufferedSocket::writeBlock(const char *data, Q_ULONG maxlen,
00191 const KSocketAddress&)
00192 {
00193
00194 return writeBlock(data, maxlen);
00195 }
00196
00197 void KBufferedSocket::enableRead(bool enable)
00198 {
00199 KStreamSocket::enableRead(enable);
00200 if (!enable && d->input)
00201 {
00202
00203 QSocketNotifier *n = socketDevice()->readNotifier();
00204 if (n)
00205 n->setEnabled(true);
00206 }
00207
00208 if (enable && state() != Connected && d->input && !d->input->isEmpty())
00209
00210
00211 QTimer::singleShot(0, this, SLOT(slotReadActivity()));
00212 }
00213
00214 void KBufferedSocket::enableWrite(bool enable)
00215 {
00216 KStreamSocket::enableWrite(enable);
00217 if (!enable && d->output && !d->output->isEmpty())
00218 {
00219
00220 QSocketNotifier *n = socketDevice()->writeNotifier();
00221 if (n)
00222 n->setEnabled(true);
00223 }
00224 }
00225
00226 void KBufferedSocket::stateChanging(SocketState newState)
00227 {
00228 if (newState == Connecting || newState == Connected)
00229 {
00230
00231
00232 if (d->input)
00233 d->input->clear();
00234 if (d->output)
00235 d->output->clear();
00236
00237
00238 enableRead(emitsReadyRead());
00239 enableWrite(emitsReadyWrite());
00240 }
00241 KStreamSocket::stateChanging(newState);
00242 }
00243
00244 void KBufferedSocket::setInputBuffering(bool enable)
00245 {
00246 QMutexLocker locker(mutex());
00247 if (!enable)
00248 {
00249 delete d->input;
00250 d->input = 0L;
00251 }
00252 else if (d->input == 0L)
00253 {
00254 d->input = new KSocketBuffer;
00255 }
00256 }
00257
00258 KIOBufferBase* KBufferedSocket::inputBuffer()
00259 {
00260 return d->input;
00261 }
00262
00263 void KBufferedSocket::setOutputBuffering(bool enable)
00264 {
00265 QMutexLocker locker(mutex());
00266 if (!enable)
00267 {
00268 delete d->output;
00269 d->output = 0L;
00270 }
00271 else if (d->output == 0L)
00272 {
00273 d->output = new KSocketBuffer;
00274 }
00275 }
00276
00277 KIOBufferBase* KBufferedSocket::outputBuffer()
00278 {
00279 return d->output;
00280 }
00281
00282 Q_ULONG KBufferedSocket::bytesToWrite() const
00283 {
00284 if (!d->output)
00285 return 0;
00286
00287 return d->output->length();
00288 }
00289
00290 void KBufferedSocket::closeNow()
00291 {
00292 KStreamSocket::close();
00293 }
00294
00295 bool KBufferedSocket::canReadLine() const
00296 {
00297 if (!d->input)
00298 return false;
00299
00300 return d->input->canReadLine();
00301 }
00302
00303 QCString KBufferedSocket::readLine()
00304 {
00305 return d->input->readLine();
00306 }
00307
00308 void KBufferedSocket::slotReadActivity()
00309 {
00310 if (d->input && state() == Connected)
00311 {
00312 mutex()->lock();
00313 Q_LONG len = d->input->receiveFrom(socketDevice());
00314
00315 if (len == -1)
00316 {
00317 if (socketDevice()->error() != WouldBlock)
00318 {
00319
00320 copyError();
00321 mutex()->unlock();
00322 emit gotError(error());
00323 closeNow();
00324 return;
00325 }
00326 }
00327 else if (len == 0)
00328 {
00329
00330 setError(IO_ReadError, RemotelyDisconnected);
00331 mutex()->unlock();
00332 emit gotError(error());
00333 closeNow();
00334 return;
00335 }
00336
00337
00338 mutex()->unlock();
00339 }
00340
00341 if (state() == Connected)
00342 KStreamSocket::slotReadActivity();
00343 else if (emitsReadyRead())
00344 {
00345 if (d->input && !d->input->isEmpty())
00346 {
00347
00348
00349 QTimer::singleShot(0, this, SLOT(slotReadActivity()));
00350 emit readyRead();
00351 }
00352 }
00353 }
00354
00355 void KBufferedSocket::slotWriteActivity()
00356 {
00357 if (d->output && !d->output->isEmpty() &&
00358 (state() == Connected || state() == Closing))
00359 {
00360 mutex()->lock();
00361 Q_LONG len = d->output->sendTo(socketDevice());
00362
00363 if (len == -1)
00364 {
00365 if (socketDevice()->error() != WouldBlock)
00366 {
00367
00368 copyError();
00369 mutex()->unlock();
00370 emit gotError(error());
00371 closeNow();
00372 return;
00373 }
00374 }
00375 else if (len == 0)
00376 {
00377
00378 setError(IO_ReadError, RemotelyDisconnected);
00379 mutex()->unlock();
00380 emit gotError(error());
00381 closeNow();
00382 return;
00383 }
00384
00385 if (d->output->isEmpty())
00386
00387
00388 socketDevice()->writeNotifier()->setEnabled(false);
00389
00390 mutex()->unlock();
00391 emit bytesWritten(len);
00392 }
00393
00394 if (state() != Closing)
00395 KStreamSocket::slotWriteActivity();
00396 else if (d->output && d->output->isEmpty() && state() == Closing)
00397 {
00398 KStreamSocket::close();
00399 }
00400 }
00401
00402 #include "kbufferedsocket.moc"
This file is part of the documentation for kdecore Library Version 3.4.2.