Remove "All rights reserved" line from license headers.
[profile/ivi/qtdeclarative.git] / src / declarative / debugger / qpacketprotocol.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtDeclarative module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qpacketprotocol_p.h"
43
44 #include <QtCore/QBuffer>
45 #include <QtCore/QElapsedTimer>
46
47 QT_BEGIN_NAMESPACE
48
49 static const unsigned int MAX_PACKET_SIZE = 0x7FFFFFFF;
50
51 /*!
52   \class QPacketProtocol
53   \internal
54
55   \brief The QPacketProtocol class encapsulates communicating discrete packets
56   across fragmented IO channels, such as TCP sockets.
57
58   QPacketProtocol makes it simple to send arbitrary sized data "packets" across
59   fragmented transports such as TCP and UDP.
60
61   As transmission boundaries are not respected, sending packets over protocols
62   like TCP frequently involves "stitching" them back together at the receiver.
63   QPacketProtocol makes this easier by performing this task for you.  Packet
64   data sent using QPacketProtocol is prepended with a 4-byte size header
65   allowing the receiving QPacketProtocol to buffer the packet internally until
66   it has all been received.  QPacketProtocol does not perform any sanity
67   checking on the size or on the data, so this class should only be used in
68   prototyping or trusted situations where DOS attacks are unlikely.
69
70   QPacketProtocol does not perform any communications itself.  Instead it can
71   operate on any QIODevice that supports the QIODevice::readyRead() signal.  A
72   logical "packet" is encapsulated by the companion QPacket class.  The
73   following example shows two ways to send data using QPacketProtocol.  The
74   transmitted data is equivalent in both.
75
76   \code
77   QTcpSocket socket;
78   // ... connect socket ...
79
80   QPacketProtocol protocol(&socket);
81
82   // Send packet the quick way
83   protocol.send() << "Hello world" << 123;
84
85   // Send packet the longer way
86   QPacket packet;
87   packet << "Hello world" << 123;
88   protocol.send(packet);
89   \endcode
90
91   Likewise, the following shows how to read data from QPacketProtocol, assuming
92   that the QPacketProtocol::readyRead() signal has been emitted.
93
94   \code
95   // ... QPacketProtocol::readyRead() is emitted ...
96
97   int a;
98   QByteArray b;
99
100   // Receive packet the quick way
101   protocol.read() >> a >> b;
102
103   // Receive packet the longer way
104   QPacket packet = protocol.read();
105   p >> a >> b;
106   \endcode
107
108   \ingroup io
109   \sa QPacket
110 */
111
112 class QPacketProtocolPrivate : public QObject
113 {
114     Q_OBJECT
115 public:
116     QPacketProtocolPrivate(QPacketProtocol *parent, QIODevice *_dev)
117         : QObject(parent), inProgressSize(-1), maxPacketSize(MAX_PACKET_SIZE),
118           waitingForPacket(false), dev(_dev)
119     {
120         Q_ASSERT(4 == sizeof(qint32));
121
122         QObject::connect(this, SIGNAL(readyRead()),
123                          parent, SIGNAL(readyRead()));
124         QObject::connect(this, SIGNAL(packetWritten()),
125                          parent, SIGNAL(packetWritten()));
126         QObject::connect(this, SIGNAL(invalidPacket()),
127                          parent, SIGNAL(invalidPacket()));
128         QObject::connect(dev, SIGNAL(readyRead()),
129                          this, SLOT(readyToRead()));
130         QObject::connect(dev, SIGNAL(aboutToClose()),
131                          this, SLOT(aboutToClose()));
132         QObject::connect(dev, SIGNAL(bytesWritten(qint64)),
133                          this, SLOT(bytesWritten(qint64)));
134     }
135
136 Q_SIGNALS:
137     void readyRead();
138     void packetWritten();
139     void invalidPacket();
140
141 public Q_SLOTS:
142     void aboutToClose()
143     {
144         inProgress.clear();
145         sendingPackets.clear();
146         inProgressSize = -1;
147     }
148
149     void bytesWritten(qint64 bytes)
150     {
151         Q_ASSERT(!sendingPackets.isEmpty());
152
153         while (bytes) {
154             if (sendingPackets.at(0) > bytes) {
155                 sendingPackets[0] -= bytes;
156                 bytes = 0;
157             } else {
158                 bytes -= sendingPackets.at(0);
159                 sendingPackets.removeFirst();
160                 emit packetWritten();
161             }
162         }
163     }
164
165     void readyToRead()
166     {
167         while (true) {
168             // Need to get trailing data
169             if (-1 == inProgressSize) {
170                 // We need a size header of sizeof(qint32)
171                 if (sizeof(qint32) > (uint)dev->bytesAvailable())
172                     return;
173
174                 // Read size header
175                 int read = dev->read((char *)&inProgressSize, sizeof(qint32));
176                 Q_ASSERT(read == sizeof(qint32));
177                 Q_UNUSED(read);
178
179                 // Check sizing constraints
180                 if (inProgressSize > maxPacketSize) {
181                     QObject::disconnect(dev, SIGNAL(readyRead()),
182                                         this, SLOT(readyToRead()));
183                     QObject::disconnect(dev, SIGNAL(aboutToClose()),
184                                         this, SLOT(aboutToClose()));
185                     QObject::disconnect(dev, SIGNAL(bytesWritten(qint64)),
186                                         this, SLOT(bytesWritten(qint64)));
187                     dev = 0;
188                     emit invalidPacket();
189                     return;
190                 }
191
192                 inProgressSize -= sizeof(qint32);
193             } else {
194                 inProgress.append(dev->read(inProgressSize - inProgress.size()));
195
196                 if (inProgressSize == inProgress.size()) {
197                     // Packet has arrived!
198                     packets.append(inProgress);
199                     inProgressSize = -1;
200                     inProgress.clear();
201
202                     waitingForPacket = false;
203                     emit readyRead();
204                 } else
205                     return;
206             }
207         }
208     }
209
210 public:
211     QList<qint64> sendingPackets;
212     QList<QByteArray> packets;
213     QByteArray inProgress;
214     qint32 inProgressSize;
215     qint32 maxPacketSize;
216     bool waitingForPacket;
217     QIODevice *dev;
218 };
219
220 /*!
221   Construct a QPacketProtocol instance that works on \a dev with the
222   specified \a parent.
223  */
224 QPacketProtocol::QPacketProtocol(QIODevice *dev, QObject *parent)
225     : QObject(parent), d(new QPacketProtocolPrivate(this, dev))
226 {
227     Q_ASSERT(dev);
228 }
229
230 /*!
231   Destroys the QPacketProtocol instance.
232  */
233 QPacketProtocol::~QPacketProtocol()
234 {
235 }
236
237 /*!
238   Returns the maximum packet size allowed.  By default this is
239   2,147,483,647 bytes.
240   
241   If a packet claiming to be larger than the maximum packet size is received,
242   the QPacketProtocol::invalidPacket() signal is emitted.
243
244   \sa QPacketProtocol::setMaximumPacketSize()
245  */
246 qint32 QPacketProtocol::maximumPacketSize() const
247 {
248     return d->maxPacketSize;
249 }
250
251 /*!
252   Sets the maximum allowable packet size to \a max.
253
254   \sa QPacketProtocol::maximumPacketSize()
255  */
256 qint32 QPacketProtocol::setMaximumPacketSize(qint32 max)
257 {
258     if (max > (signed)sizeof(qint32))
259         d->maxPacketSize = max;
260     return d->maxPacketSize;
261 }
262
263 /*!
264   Returns a streamable object that is transmitted on destruction.  For example
265
266   \code
267   protocol.send() << "Hello world" << 123;
268   \endcode
269
270   will send a packet containing "Hello world" and 123.  To construct more
271   complex packets, explicitly construct a QPacket instance.
272  */
273 QPacketAutoSend QPacketProtocol::send()
274 {
275     return QPacketAutoSend(this);
276 }
277
278 /*!
279   \fn void QPacketProtocol::send(const QPacket & packet)
280
281   Transmit the \a packet.
282  */
283 void QPacketProtocol::send(const QPacket & p)
284 {
285     if (p.b.isEmpty())
286         return; // We don't send empty packets
287
288     qint64 sendSize = p.b.size() + sizeof(qint32);
289
290     d->sendingPackets.append(sendSize);
291     qint32 sendSize32 = sendSize;
292     qint64 writeBytes = d->dev->write((char *)&sendSize32, sizeof(qint32));
293     Q_ASSERT(writeBytes == sizeof(qint32));
294     writeBytes = d->dev->write(p.b);
295     Q_ASSERT(writeBytes == p.b.size());
296 }
297
298 /*!
299   Returns the number of received packets yet to be read.
300   */
301 qint64 QPacketProtocol::packetsAvailable() const
302 {
303     return d->packets.count();
304 }
305
306 /*!
307   Discard any unread packets.
308   */
309 void QPacketProtocol::clear()
310 {
311     d->packets.clear();
312 }
313
314 /*!
315   Return the next unread packet, or an invalid QPacket instance if no packets
316   are available.  This method does NOT block.
317   */
318 QPacket QPacketProtocol::read()
319 {
320     if (0 == d->packets.count())
321         return QPacket();
322
323     QPacket rv(d->packets.at(0));
324     d->packets.removeFirst();
325     return rv;
326 }
327
328 /*
329    Returns the difference between msecs and elapsed. If msecs is -1,
330    however, -1 is returned.
331 */
332 static int qt_timeout_value(int msecs, int elapsed)
333 {
334     if (msecs == -1)
335         return -1;
336
337     int timeout = msecs - elapsed;
338     return timeout < 0 ? 0 : timeout;
339 }
340
341 /*!
342   This function locks until a new packet is available for reading and the
343   \l{QIODevice::}{readyRead()} signal has been emitted. The function
344   will timeout after \a msecs milliseconds; the default timeout is
345   30000 milliseconds.
346
347   The function returns true if the readyRead() signal is emitted and
348   there is new data available for reading; otherwise it returns false
349   (if an error occurred or the operation timed out).
350   */
351
352 bool QPacketProtocol::waitForReadyRead(int msecs)
353 {
354     if (!d->packets.isEmpty())
355         return true;
356
357     QElapsedTimer stopWatch;
358     stopWatch.start();
359
360     d->waitingForPacket = true;
361     do {
362         if (!d->dev->waitForReadyRead(msecs))
363             return false;
364         if (!d->waitingForPacket)
365             return true;
366         msecs = qt_timeout_value(msecs, stopWatch.elapsed());
367     } while (true);
368 }
369
370 /*!
371   Return the QIODevice passed to the QPacketProtocol constructor.
372 */
373 QIODevice *QPacketProtocol::device()
374 {
375     return d->dev;
376 }
377
378 /*!
379   \fn void QPacketProtocol::readyRead()
380
381   Emitted whenever a new packet is received.  Applications may use
382   QPacketProtocol::read() to retrieve this packet.
383  */
384
385 /*!
386   \fn void QPacketProtocol::invalidPacket()
387
388   A packet larger than the maximum allowable packet size was received.  The
389   packet will be discarded and, as it indicates corruption in the protocol, no
390   further packets will be received.
391  */
392
393 /*!
394   \fn void QPacketProtocol::packetWritten()
395
396   Emitted each time a packet is completing written to the device.  This signal
397   may be used for communications flow control.
398  */
399
400 /*!
401   \class QPacket
402   \internal
403
404   \brief The QPacket class encapsulates an unfragmentable packet of data to be
405   transmitted by QPacketProtocol.
406
407   The QPacket class works together with QPacketProtocol to make it simple to
408   send arbitrary sized data "packets" across fragmented transports such as TCP
409   and UDP.
410
411   QPacket provides a QDataStream interface to an unfragmentable packet.
412   Applications should construct a QPacket, propagate it with data and then
413   transmit it over a QPacketProtocol instance.  For example:
414   \code
415   QPacketProtocol protocol(...);
416
417   QPacket myPacket;
418   myPacket << "Hello world!" << 123;
419   protocol.send(myPacket);
420   \endcode
421
422   As long as both ends of the connection are using the QPacketProtocol class,
423   the data within this packet will be delivered unfragmented at the other end,
424   ready for extraction.
425
426   \code
427   QByteArray greeting;
428   int count;
429
430   QPacket myPacket = protocol.read();
431
432   myPacket >> greeting >> count;
433   \endcode
434
435   Only packets returned from QPacketProtocol::read() may be read from.  QPacket
436   instances constructed by directly by applications are for transmission only
437   and are considered "write only".  Attempting to read data from them will
438   result in undefined behavior.
439
440   \ingroup io
441   \sa QPacketProtocol
442  */
443
444 /*!
445   Constructs an empty write-only packet.
446   */
447 QPacket::QPacket()
448     : QDataStream(), buf(0)
449 {
450     buf = new QBuffer(&b);
451     buf->open(QIODevice::WriteOnly);
452     setDevice(buf);
453     setVersion(QDataStream::Qt_4_7);
454 }
455
456 /*!
457   Destroys the QPacket instance.
458   */
459 QPacket::~QPacket()
460 {
461     if (buf) {
462         delete buf;
463         buf = 0;
464     }
465 }
466
467 /*!
468   Creates a copy of \a other.  The initial stream positions are shared, but the
469   two packets are otherwise independent.
470  */
471 QPacket::QPacket(const QPacket & other)
472     : QDataStream(), b(other.b), buf(0)
473 {
474     buf = new QBuffer(&b);
475     buf->open(other.buf->openMode());
476     setDevice(buf);
477 }
478
479 /*!
480   \internal
481   */
482 QPacket::QPacket(const QByteArray & ba)
483     : QDataStream(), b(ba), buf(0)
484 {
485     buf = new QBuffer(&b);
486     buf->open(QIODevice::ReadOnly);
487     setDevice(buf);
488 }
489
490 /*!
491   Returns true if this packet is empty - that is, contains no data.
492   */
493 bool QPacket::isEmpty() const
494 {
495     return b.isEmpty();
496 }
497
498 /*!
499   Returns raw packet data.
500   */
501 QByteArray QPacket::data() const
502 {
503     return b;
504 }
505
506 /*!
507   Clears data in the packet.  This is useful for reusing one writable packet.
508   For example
509   \code
510   QPacketProtocol protocol(...);
511
512   QPacket packet;
513
514   packet << "Hello world!" << 123;
515   protocol.send(packet);
516
517   packet.clear();
518   packet << "Goodbyte world!" << 789;
519   protocol.send(packet);
520   \endcode
521  */
522 void QPacket::clear()
523 {
524     QBuffer::OpenMode oldMode = buf->openMode();
525     buf->close();
526     b.clear();
527     buf->setBuffer(&b); // reset QBuffer internals with new size of b.
528     buf->open(oldMode);
529 }
530
531 /*!
532   \class QPacketAutoSend
533   \internal
534
535   \internal
536   */
537 QPacketAutoSend::QPacketAutoSend(QPacketProtocol *_p)
538     : QPacket(), p(_p)
539 {
540 }
541
542 QPacketAutoSend::~QPacketAutoSend()
543 {
544     if (!b.isEmpty())
545         p->send(*this);
546 }
547
548 QT_END_NAMESPACE
549
550 #include <qpacketprotocol.moc>