UdpSwitch.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "Qt.h"
00024 #include "Imports.h"
00025 #include "UdpSwitch.h"
00026 #include "UdpConnection.h"
00027
00028 namespace Protocols {
00029 namespace Transports {
00030
00031 enum Constants
00032 {
00033 MaximalReadBufferLength = 4096
00034 };
00035
00036 class UdpSwitchPrivate
00037 {
00038 REFERENCE_OBJECT (UdpSwitchPrivate)
00039
00040 public:
00041 typedef QMap <NodeAddress, UdpConnection *> ReadMap;
00042 typedef QMap <UdpConnection *, NodeAddress> WriteMap;
00043
00044 QUdpSocket *socket;
00045 bool isStarted;
00046 bool isAcceptingIncomingConnections;
00047 ReadMap readMap;
00048 WriteMap writeMap;
00049
00050 UdpSwitchPrivate()
00051 : socket (new QUdpSocket), isStarted (false),
00052 isAcceptingIncomingConnections (false), readMap(), writeMap()
00053 {}
00054
00055 ~UdpSwitchPrivate()
00056 {
00057 delete socket;
00058 }
00059 };
00060
00061 }
00062 }
00063
00064 using namespace Protocols::Transports;
00065
00066 UdpSwitch::UdpSwitch()
00067 : p (new UdpSwitchPrivate())
00068 {
00069 QObject::connect (p->socket, SIGNAL (readyRead()), this, SLOT (readyRead()));
00070 }
00071
00072 UdpSwitch::~UdpSwitch()
00073 {
00074 delete p;
00075 }
00076
00078
00093 bool UdpSwitch::start (const NodeAddress &switchAddress,
00094 bool acceptIncomingConnections)
00095 {
00096 p->isAcceptingIncomingConnections = acceptIncomingConnections;
00097 p->isStarted = p->socket->bind (switchAddress.hostAddress(),
00098 switchAddress.hostPort());
00099
00100 return p->isStarted;
00101 }
00102
00103 void UdpSwitch::stop()
00104 {
00105 Q_ASSERT (p->isStarted);
00106
00107 p->socket->close();
00108 p->isStarted = false;
00109
00110
00111 }
00112
00113 bool UdpSwitch::openChannel (UdpConnection *udpConnection,
00114 const NodeAddress &nodeAddress)
00115 {
00116 Q_ASSERT (p->isStarted);
00117
00118
00119 if (p->readMap.contains (nodeAddress) || p->writeMap.contains (udpConnection))
00120 return false;
00121
00122 p->readMap.insert (nodeAddress, udpConnection);
00123 p->writeMap.insert (udpConnection, nodeAddress);
00124 return true;
00125 }
00126
00127 void UdpSwitch::closeChannel (UdpConnection *udpConnection)
00128 {
00129 Q_ASSERT (p->isStarted);
00130 Q_ASSERT (p->writeMap.contains (udpConnection));
00131
00132 NodeAddress nodeAddress = p->writeMap.take (udpConnection);
00133 p->readMap.take (nodeAddress);
00134 }
00135
00136 bool UdpSwitch::writeDatagram (UdpConnection *udpConnection,
00137 const char * data, qint64 maxSize)
00138 {
00139 Q_ASSERT (p->isStarted);
00140 Q_ASSERT (p->writeMap.contains (udpConnection));
00141
00142 NodeAddress nodeAddress = p->writeMap.value (udpConnection);
00143 qint64 bytesWritten = p->socket->writeDatagram (data, maxSize,
00144 nodeAddress.hostAddress(),
00145 nodeAddress.hostPort());
00146
00147 Q_ASSERT (bytesWritten == -1 || bytesWritten == maxSize);
00148 return bytesWritten == maxSize;
00149 }
00150
00151 void UdpSwitch::readyRead()
00152 {
00153 Q_ASSERT (p->isStarted);
00154
00155 if (!p->socket->hasPendingDatagrams())
00156 return;
00157
00158 char buffer [MaximalReadBufferLength];
00159 QHostAddress hostAddress;
00160 quint16 hostPort;
00161
00162
00163
00164
00165
00166 qint64 bytesRead = p->socket->readDatagram (buffer, MaximalReadBufferLength,
00167 &hostAddress, &hostPort);
00168
00169 NodeAddress nodeAddress (hostAddress, hostPort);
00170 UdpSwitchPrivate::ReadMap::iterator it = p->readMap.find (nodeAddress);
00171 if (it != p->readMap.end()) {
00172 (*it)->datagramRead (QByteArray (buffer, bytesRead));
00173 } else if (p->isAcceptingIncomingConnections) {
00174 UdpConnection *incomingConnection = new UdpConnection (this);
00175 incomingConnection->connectToNode (nodeAddress);
00176
00177 Q_ASSERT (incomingConnection->state() == Connection::ConnectedState);
00178 incomingConnection->datagramRead (QByteArray (buffer, bytesRead));
00179 emit connectionAccepted (incomingConnection);
00180 }
00181 }