Qt 4.8
qpacketprotocol.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtDeclarative module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "private/qpacketprotocol_p.h"
43 
44 #include <QBuffer>
45 #include <QElapsedTimer>
46 
48 
49 #define MAX_PACKET_SIZE 0x7FFFFFFF
50 
116 {
117 Q_OBJECT
118 public:
121  waitingForPacket(false), dev(_dev)
122  {
123  Q_ASSERT(4 == sizeof(qint32));
124 
126  parent, SIGNAL(readyRead()));
128  parent, SIGNAL(packetWritten()));
130  parent, SIGNAL(invalidPacket()));
132  this, SLOT(readyToRead()));
134  this, SLOT(aboutToClose()));
136  this, SLOT(bytesWritten(qint64)));
137  }
138 
139 Q_SIGNALS:
140  void readyRead();
141  void packetWritten();
142  void invalidPacket();
143 
144 public Q_SLOTS:
146  {
147  inProgress.clear();
149  inProgressSize = -1;
150  }
151 
152  void bytesWritten(qint64 bytes)
153  {
155 
156  while(bytes) {
157  if(sendingPackets.at(0) > bytes) {
158  sendingPackets[0] -= bytes;
159  bytes = 0;
160  } else {
161  bytes -= sendingPackets.at(0);
164  }
165  }
166  }
167 
168  void readyToRead()
169  {
170  bool gotPackets = false;
171  while (true) {
172  // Get size header (if not in progress)
173  if (-1 == inProgressSize) {
174  // We need a size header of sizeof(qint32)
175  if (sizeof(qint32) > (uint)dev->bytesAvailable()) {
176  if (gotPackets)
177  emit readyRead();
178  return; // no more data available
179  }
180 
181  // Read size header
182  int read = dev->read((char *)&inProgressSize, sizeof(qint32));
183  Q_ASSERT(read == sizeof(qint32));
184  Q_UNUSED(read);
185 
186  // Check sizing constraints
187  if (inProgressSize > maxPacketSize) {
189  this, SLOT(readyToRead()));
191  this, SLOT(aboutToClose()));
193  this, SLOT(bytesWritten(qint64)));
194  dev = 0;
196  return;
197  }
198 
199  inProgressSize -= sizeof(qint32);
200  } else {
202 
203  if (inProgressSize == inProgress.size()) {
204  // Packet has arrived!
206  inProgressSize = -1;
207  inProgress.clear();
208 
209  waitingForPacket = false;
210  gotPackets = true;
211  } else {
212  if (gotPackets)
213  emit readyRead();
214  return; // packet in progress is not yet complete
215  }
216  }
217  }
218  }
219 
220 public:
228 };
229 
235 : QObject(parent), d(new QPacketProtocolPrivate(this, dev))
236 {
237  Q_ASSERT(dev);
238 }
239 
244 {
245 }
246 
257 {
258  return d->maxPacketSize;
259 }
260 
267 {
268  if(max > (signed)sizeof(qint32))
269  d->maxPacketSize = max;
270  return d->maxPacketSize;
271 }
272 
284 {
285  return QPacketAutoSend(this);
286 }
287 
297 {
298  if(p.b.isEmpty())
299  return; // We don't send empty packets
300 
301  qint64 sendSize = p.b.size() + sizeof(qint32);
302 
303  d->sendingPackets.append(sendSize);
304  qint32 sendSize32 = sendSize;
305  qint64 writeBytes = d->dev->write((char *)&sendSize32, sizeof(qint32));
306  Q_ASSERT(writeBytes == sizeof(qint32));
307  writeBytes = d->dev->write(p.b);
308  Q_ASSERT(writeBytes == p.b.size());
309 }
310 
315 {
316  return d->packets.count();
317 }
318 
323 {
324  d->packets.clear();
325 }
326 
332 {
333  if(0 == d->packets.count())
334  return QPacket();
335 
336  QPacket rv(d->packets.at(0));
337  d->packets.removeFirst();
338  return rv;
339 }
340 
341 /*
342  Returns the difference between msecs and elapsed. If msecs is -1,
343  however, -1 is returned.
344 */
345 static int qt_timeout_value(int msecs, int elapsed)
346 {
347  if (msecs == -1)
348  return -1;
349 
350  int timeout = msecs - elapsed;
351  return timeout < 0 ? 0 : timeout;
352 }
353 
366 {
367  if (!d->packets.isEmpty())
368  return true;
369 
370  QElapsedTimer stopWatch;
371  stopWatch.start();
372 
373  d->waitingForPacket = true;
374  do {
375  if (!d->dev->waitForReadyRead(msecs))
376  return false;
377  if (!d->waitingForPacket)
378  return true;
379  msecs = qt_timeout_value(msecs, stopWatch.elapsed());
380  } while (true);
381 }
382 
387 {
388  return d->dev;
389 }
390 
473 : QDataStream(), buf(0)
474 {
475  buf = new QBuffer(&b);
477  setDevice(buf);
479 }
480 
485 {
486  if(buf) {
487  delete buf;
488  buf = 0;
489  }
490 }
491 
496 QPacket::QPacket(const QPacket & other)
497 : QDataStream(), b(other.b), buf(0)
498 {
499  buf = new QBuffer(&b);
500  buf->open(other.buf->openMode());
501  setDevice(buf);
502 }
503 
508 : QDataStream(), b(ba), buf(0)
509 {
510  buf = new QBuffer(&b);
512  setDevice(buf);
513 }
514 
518 bool QPacket::isEmpty() const
519 {
520  return b.isEmpty();
521 }
522 
527 {
528  return b;
529 }
530 
548 {
549  QBuffer::OpenMode oldMode = buf->openMode();
550  buf->close();
551  b.clear();
552  buf->setBuffer(&b); // reset QBuffer internals with new size of b.
553  buf->open(oldMode);
554 }
555 
563 : QPacket(), p(_p)
564 {
565 }
566 
568 {
569  if(!b.isEmpty())
570  p->send(*this);
571 }
572 
574 
575 #include <qpacketprotocol.moc>
double d
Definition: qnumeric_p.h:62
static double elapsed(qint64 after, qint64 before)
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
int qint32
Definition: qglobal.h:937
virtual bool waitForReadyRead(int msecs)
Blocks until new data is available for reading and the readyRead() signal has been emitted...
Definition: qiodevice.cpp:1616
virtual ~QPacketAutoSend()
virtual ~QPacketProtocol()
Destroys the QPacketProtocol instance.
QByteArray & append(char c)
Appends the character ch to this byte array.
static int qt_timeout_value(int msecs, int elapsed)
bool open(OpenMode openMode)
Reimplemented Function
Definition: qbuffer.cpp:338
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
void close()
Reimplemented Function
Definition: qbuffer.cpp:359
#define SLOT(a)
Definition: qobjectdefs.h:226
The QPacketProtocol class encapsulates communicating discrete packets across fragmented IO channels...
QPacketAutoSend send()
Returns a streamable object that is transmitted on destruction.
int count(const T &t) const
Returns the number of occurrences of value in the list.
Definition: qlist.h:891
#define Q_SLOTS
Definition: qobjectdefs.h:71
The QBuffer class provides a QIODevice interface for a QByteArray.
Definition: qbuffer.h:57
#define MAX_PACKET_SIZE
void bytesWritten(qint64 bytes)
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
The QObject class is the base class of all Qt objects.
Definition: qobject.h:111
void setBuffer(QByteArray *a)
Makes QBuffer uses the QByteArray pointed to by byteArray as its internal buffer. ...
Definition: qbuffer.cpp:248
#define Q_SIGNALS
Definition: qobjectdefs.h:72
The QElapsedTimer class provides a fast way to calculate elapsed times.
Definition: qelapsedtimer.h:53
The QPacket class encapsulates an unfragmentable packet of data to be transmitted by QPacketProtocol...
qint64 elapsed() const
Returns the number of milliseconds since this QElapsedTimer was last started.
bool isEmpty() const
Returns true if the list contains no items; otherwise returns false.
Definition: qlist.h:152
void setVersion(int)
Sets the version number of the data serialization format to v.
Definition: qdatastream.h:215
bool waitForReadyRead(int msecs=3000)
This function locks until a new packet is available for reading and the QIODevice::readyRead() signal...
qint64 read(char *data, qint64 maxlen)
Reads at most maxSize bytes from the device into data, and returns the number of bytes read...
Definition: qiodevice.cpp:791
#define SIGNAL(a)
Definition: qobjectdefs.h:227
void append(const T &t)
Inserts value at the end of the list.
Definition: qlist.h:507
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
qint32 setMaximumPacketSize(qint32)
Sets the maximum allowable packet size to max.
static bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
Creates a connection of the given type from the signal in the sender object to the method in the rece...
Definition: qobject.cpp:2580
QPacketAutoSend(QPacketProtocol *)
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
#define emit
Definition: qobjectdefs.h:76
QByteArray data() const
Returns raw packet data.
unsigned int uint
Definition: qglobal.h:996
void removeFirst()
Removes the first item in the list.
Definition: qlist.h:286
void clear()
Removes all items from the list.
Definition: qlist.h:764
__int64 qint64
Definition: qglobal.h:942
#define Q_OBJECT
Definition: qobjectdefs.h:157
QPacketProtocolPrivate * d
void clear()
Discard any unread packets.
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
Disconnects signal in object sender from method in object receiver.
Definition: qobject.cpp:2895
void clear()
Clears data in the packet.
QPacket()
Constructs an empty write-only packet.
OpenMode openMode() const
Returns the mode in which the device has been opened; i.e.
Definition: qiodevice.cpp:465
QList< QByteArray > packets
qint64 packetsAvailable() const
Returns the number of received packets yet to be read.
QObject * parent() const
Returns a pointer to the parent object.
Definition: qobject.h:273
virtual qint64 bytesAvailable() const
Returns the number of bytes that are available for reading.
Definition: qiodevice.cpp:752
int size() const
Returns the number of bytes in this byte array.
Definition: qbytearray.h:402
QByteArray b
bool isEmpty() const
Returns true if this packet is empty - that is, contains no data.
qint32 maximumPacketSize() const
Returns the maximum packet size allowed.
void setDevice(QIODevice *)
void QDataStream::setDevice(QIODevice *d)
bool isEmpty() const
Returns true if the byte array has size 0; otherwise returns false.
Definition: qbytearray.h:421
QBuffer * buf
The QDataStream class provides serialization of binary data to a QIODevice.
Definition: qdatastream.h:71
QList< qint64 > sendingPackets
QPacket read()
Return the next unread packet, or an invalid QPacket instance if no packets are available.
qint64 write(const char *data, qint64 len)
Writes at most maxSize bytes of data from data to the device.
Definition: qiodevice.cpp:1342
QPacketProtocolPrivate(QPacketProtocol *parent, QIODevice *_dev)
QIODevice * device()
Return the QIODevice passed to the QPacketProtocol constructor.
The QIODevice class is the base interface class of all I/O devices in Qt.
Definition: qiodevice.h:66
virtual ~QPacket()
Destroys the QPacket instance.
QPacketProtocol * p
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729
void start()
Starts this timer.
QPacketProtocol(QIODevice *dev, QObject *parent=0)
Construct a QPacketProtocol instance that works on dev with the specified parent. ...
void clear()
Clears the contents of the byte array and makes it empty.