UdpConnection.cpp

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 2005-2007 by Peter Dimov.
00004 
00005 This file is part of Calitko (http://www.calitko.org).
00006 
00007 Calitko is free software; you can redistribute it and/or modify
00008 it under the terms of the GNU General Public License as published by
00009 the Free Software Foundation; either version 2 of the License, or
00010 (at your option) any later version.
00011 
00012 Calitko is distributed in the hope that it will be useful,
00013 but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Calitko; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 
00021 */
00022 
00023 #include "Qt.h"
00024 #include "Imports.h"
00025 #include "UdpConnection.h"
00026 #include "UdpSwitch.h"
00027 
00028 namespace Protocols {
00029 namespace Transports {
00030 
00031 // \todo Fix this warning:
00032 // Protocols/Transports/UdpConnection.cpp(40): warning #1944: declaration of "udpSwitch" shadows a member of 'this'
00033 class UdpConnectionPrivate
00034 {
00035     REFERENCE_OBJECT (UdpConnectionPrivate)
00036 
00037 public:
00038     UdpSwitch               *udpSwitch;
00039     QQueue <QByteArray>     readQueue;
00040     qint64                  headDatagramReadBytes;
00041 
00042     UdpConnectionPrivate (UdpSwitch *udpSwitch)
00043      :  udpSwitch (udpSwitch), readQueue(), headDatagramReadBytes (0)
00044     {}
00045 };
00046 
00047 } // namespace Transports;
00048 } // namespace Protocols;
00049 
00050 using namespace Protocols::Transports;
00051 
00052 UdpConnection::UdpConnection (UdpSwitch *udpSwitch)
00053     : p (new UdpConnectionPrivate (udpSwitch))
00054 {
00055     // \todo connect a signal telling that the udp swith is stopped?
00056 }
00057 
00058 UdpConnection::~UdpConnection()
00059 {
00060     //Q_ASSERT (state() == DisconnectedState);
00061 }
00062 
00063 void UdpConnection::doConnectToNode (const NodeAddress &nodeAddress)
00064 {
00065     Q_ASSERT (!nodeAddress.isNull());
00066 
00067     if (p->udpSwitch->openChannel (this, nodeAddress)) {
00068         setState (Connection::ConnectedState);
00069         setOpenMode (QIODevice::ReadWrite | QIODevice::Unbuffered);
00070         // \todo delay emiting these signals ?
00071         emit connectionEstablished();
00072     } else {
00073         emit connectionFailed();
00074     }
00075 }
00076 
00077 void UdpConnection::doDisconnectFromNode()
00078 {
00079     p->udpSwitch->closeChannel (this);
00080     setOpenMode (QIODevice::NotOpen);
00081     // \todo Delay emiting this signal?
00082     emit connectionClosed();
00083 }
00084 
00085 void UdpConnection::datagramRead (const QByteArray &datagram)
00086 {
00087     p->readQueue.enqueue (datagram);
00088     emit readyRead();
00089 }
00090 
00091 qint64 UdpConnection::readData (char * data, qint64 maxSize)
00092 {
00093     // \todo This implementation, as already noted in another todo in the class
00094     // description is not consistent with the documentation. Changing it would
00095     // require changing PacketReader as well and this is not necessary yet.
00096     if (p->readQueue.isEmpty())
00097         return 0;
00098 
00099     if (p->readQueue.head().length() - p->headDatagramReadBytes >= maxSize) {
00100         memcpy (data, p->readQueue.head().data() + p->headDatagramReadBytes, maxSize);
00101         p->headDatagramReadBytes += maxSize;
00102         if (p->headDatagramReadBytes == p->readQueue.head().length()) {
00103             p->headDatagramReadBytes = 0;
00104             p->readQueue.dequeue();
00105         }
00106         return maxSize;
00107     } else {
00108         // \todo emit readError()
00109         return -1;
00110     }
00111 }
00112 
00113 qint64 UdpConnection::writeData (const char * data, qint64 maxSize)
00114 {
00115     if (p->udpSwitch->writeDatagram (this, data, maxSize)) {
00116         // do a delayed emit bytesWritten (maxSize);
00117         QMetaObject::invokeMethod (this, "bytesWritten", Qt::QueuedConnection,
00118                                    QGenericReturnArgument(),
00119                                    Q_ARG (qint64, maxSize));
00120         return maxSize;
00121     } else {
00122         //\tood emit writeError();
00123         return -1;
00124     }
00125 }