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