Jean-Yves Didier

Grosses corrections de bugs sur le protocole réseau.

Définition des vraies erreurs du protocole (et non pas des programmes).
\documentclass[a4paper,12pt]{article}
\usepackage[margin=2cm]{geometry}
\usepackage{times}
\title{ARCS Network module protocol specification}
\author{Jean-Yves Didier}
\begin{document}
\maketitle
\hspace{0.5cm}
\hrule
\hspace{0.5cm}
\tabelofcontents
\newpage
The ARCS network module intends to ...
\section{Definitions}
\paragraph{Server}
\paragraph{Client}
\paragraph{Master}
\paragraph{Slave}
\section{Use cases}
\section{Frame specifications}
\section{Reference implementation}
\end{document}
\ No newline at end of file
......@@ -181,18 +181,25 @@ void ARCSNetworkComponent::requestSlotConnect(ARCSNetworkProxySlot* anps) //chec
if (response )
{
if (response->getType() != ARCSNetworkFrame::SLOT_RESPONSE)
//! \todo insérer traitement approprié
ARCS::Network::logError(486);
{
//! \todo polish this thing
if (response->getType() == ARCSNetworkFrame::ERR_RESPONSE)
ARCS::Network::logError(
((ARCSNetworkErrResponse*)response->getData())->getErrId(),
QString("for '") + this->getProperty("id").toString()+
"." + anps->getSlot() +"' (slot request)."
);
else
ARCS::Network::logError(486);
}
else
{
anps->setSlotId(((ARCSNetworkSlotResponse*)response->getData())->getId());
}
delete response;
}
else
ARCS::Network::logError(488,socket->errorString());
if (response)
delete response;
}
......@@ -221,10 +228,19 @@ void ARCSNetworkComponent::requestSignalConnect(ARCSNetworkProxySignal* anps) //
}
ARCSNetworkFrame* response = ARCSNetworkFrame::readFrame(socket.data());
//! \todo insert something here in case of an error
if (response)
{
if (response->getType() == ARCSNetworkFrame::ERR_RESPONSE)
{
ARCS::Network::logError(
((ARCSNetworkErrResponse*)response->getData())->getErrId(),
QString("for '") + this->getProperty("id").toString()+
"." + anps->getSignal() +"' (signal request)."
);
}
delete response;
//! \todo work on response to signal_request
}
}
void ARCSNetworkComponent::requestSignalDisconnect(ARCSNetworkProxySignal* anps) //check
......@@ -248,10 +264,18 @@ void ARCSNetworkComponent::requestSignalDisconnect(ARCSNetworkProxySignal* anps)
}
ARCSNetworkFrame* response = ARCSNetworkFrame::readFrame(socket.data());
//! \todo insert something here in case of an error
if (response)
{
if (response->getType() == ARCSNetworkFrame::ERR_RESPONSE)
{
ARCS::Network::logError(
((ARCSNetworkErrResponse*)response->getData())->getErrId(),
QString("for '") + this->getProperty("id").toString()+
"." + anps->getSignal() +"' (signal disconnect)."
);
}
delete response;
//! \todo work on response to signal_request
}
socket->disconnectFromHost();
}
......@@ -287,16 +311,27 @@ bool ARCSNetworkComponent::genuineConnect (QString sig, ARCSAbstractComponent *d
return false;
}
ARCSNetworkFrame* response = ARCSNetworkFrame::readFrame(socket.data());
//! \todo insert something here in case of an error
//! \todo consume response appropriately
if (response)
{
if (response->getType() == ARCSNetworkFrame::ERR_RESPONSE)
{
ARCS::Network::logError(
((ARCSNetworkErrResponse*)response->getData())->getErrId(),
QString("for '") + this->getProperty("id").toString()+
"." + sig +"' to '" + dst->getProperty("id").toString() +
"." + slt +"' (connection request)."
);
delete response;
return false;
}
delete response;
}
//! \todo work on response to signal_request
return true;
}
bool ARCSNetworkComponent::genuineDisconnect(QString sig, ARCSAbstractComponent* , QString ) //check
bool ARCSNetworkComponent::genuineDisconnect(QString sig, ARCSAbstractComponent* dst, QString slt) //check
{
QSharedPointer<QTcpSocket> socket(new QTcpSocket());
socket->connectToHost(hostName, port);
......@@ -315,12 +350,23 @@ bool ARCSNetworkComponent::genuineDisconnect(QString sig, ARCSAbstractComponent*
ARCS::Network::logError(429,socket->errorString());
return false;
}
ARCSNetworkFrame* response = ARCSNetworkFrame::readFrame(socket.data());
//! \todo insert something here in case of an error
//! \todo consume response appropriately
if (response)
{
if (response->getType() == ARCSNetworkFrame::ERR_RESPONSE)
{
ARCS::Network::logError(
((ARCSNetworkErrResponse*)response->getData())->getErrId(),
QString("for '") + this->getProperty("id").toString()+
"." + sig +"' to '" + dst->getProperty("id").toString() +
"." + slt +"' (disconnection request)."
);
delete response;
return false;
}
delete response;
//! \todo work on response to signal_request
}
return true;
}
......
......@@ -30,6 +30,20 @@ QHash<int,QString> ARCS::Network::initErrors()
{
QHash<int,QString> res;
res[10]="Interface not bound %1";
res[11]="Could not connect to remote component %1";
res[12]="Could not send frame to remote component %1";
// the error response should be declined in several other problems.
res[13]="Received an error response from remote component %1";
res[14]="Received null response from remote component %1";
res[15]="Error response from remote component : undefined slot %1";
res[16]="Error response from remote component : undefined signal %1";
res[17]="Error response from remote component : wrong id %1";
res[25]="Undefined slot %1";
res[26]="Undefined signal %1";
res[27]="Wrong id %1";
///////////////////////////////////////////////////////////////////////////
// general errors
res[600]="error while receiving frame: '%1'";
......@@ -93,6 +107,8 @@ QHash<int,QString> ARCS::Network::initErrors()
res[585]="SLOT_RESPONSE: wrong slot name (%1)";
res[589]="SLOT_RESPONSE: error while writing frame: '%1'";
res[599]="ERR_RESPONSE: error while writing frame: '%1'";
return res;
}
......
......@@ -58,7 +58,7 @@ int ARCSNetworkProxySignal::cleanSignalConnect(QString, QString, QString, QStrin
}
void ARCSNetworkProxySignal::call(QStringList sl)
bool ARCSNetworkProxySignal::call(QStringList sl)
{
//1 prparer les donnes
int nbargs = sl.count();
......@@ -77,7 +77,7 @@ void ARCSNetworkProxySignal::call(QStringList sl)
if (nbargs > typeIds.count())
{
std::cerr << "[Network] Argument and type count mismatch (" << nbargs << ", "<< typeIds.count() << ")" << std::endl;
return ;
return false ;
}
for (int i = 0; i < nbargs; i++)
......@@ -89,4 +89,5 @@ void ARCSNetworkProxySignal::call(QStringList sl)
//2 lancer l'appel l'aide de qt_metacall() ou qt_activate()
qt_metacall( QMetaObject::InvokeMetaMethod ,metaObject()->methodCount(),args);
return true;
}
......
......@@ -26,7 +26,7 @@ public:
virtual int cleanSignalConnect(QString, QString, QString, QString);
void setSignal(QString s);
void call(QStringList sl);
bool call(QStringList sl);
QString getSignal() { return signalName; }
void setId(int i) { id = i; }
int getId() { return id; }
......
......@@ -2,6 +2,7 @@
#include "arcsnetworkframes.h"
#include "arcsnetworkserver.h"
#include "arcsnetworkcomponent.h"
#include <arcs/arcsapplicationcomponent.h>
#include <arcs/arcsfactory.h>
#include <QTcpSocket>
#include <QSharedPointer>
......@@ -60,11 +61,18 @@ int ARCSNetworkProxySlot::qt_metacall(QMetaObject::Call call,int id, void** argu
}
ARCSNetworkFrame* response = ARCSNetworkFrame::readFrame(socket.data());
//! \todo handle response appropriately
// traitement de response -> Non c'est juste pour attendre de manire bloquante !
if (response)
{
if (response->getType() == ARCSNetworkFrame::ERR_RESPONSE)
{
ARCS::Network::logError(
((ARCSNetworkErrResponse*)response->getData())->getErrId(),
QString("for slot id '") + slotId +"' (call request)."
);
}
delete response;
}
return -1;
}
......@@ -83,12 +91,22 @@ void ARCSNetworkProxySlot::setSlot(QString s)
int ARCSNetworkProxySlot::prepareSlotConnect(QString , QString sltName, QString , QString , bool simulate)
int ARCSNetworkProxySlot::prepareSlotConnect(QString , QString sltName, QString objectName , QString , bool simulate)
{
if (simulate)
return 0;
ARCSNetworkComponent* anc = dynamic_cast<ARCSNetworkComponent*>(home);
ARCSNetworkComponent* anc2 = dynamic_cast<ARCSNetworkComponent*>(
ARCSApplicationComponent::getRunningInstance()->getContext()->getComponent(objectName)
);
// if anc2 is also a remote component then it is a connection between two
// remote components, thus it is not necessary to handle it here.
if (anc2 && anc)
return -1;
if (anc)
anc->requestSlotConnect(this);
//! \todo insrer ici un traitement appropri
......
......@@ -16,13 +16,16 @@ class ARCSNetworkProxySlot : public QObject, public ARCSQDynamicObject
public:
ARCSNetworkProxySlot(ARCSAbstractComponent* aac, QObject* parent=0);
virtual int qt_metacall(QMetaObject::Call call, int id, void ** arguments);
virtual int qt_metacall(QMetaObject::Call call, int id, void** arguments);
virtual QStringList getSignalList() { return QStringList(); }
virtual QStringList getSlotList() { return QStringList(slotName);}
virtual int prepareSlotConnect(QString sigName, QString sltName, QString objectName = QString::null, QString actualSignal = QString::null, bool simulate = false) ;
virtual int prepareSlotConnect(QString sigName, QString sltName,
QString objectName = QString::null,
QString actualSignal = QString::null,
bool simulate = false) ;
virtual int prepareSignalConnect(QString, QString, QString, QString, bool)
{ return -1;}
......
......@@ -8,6 +8,7 @@
#include <QSharedPointer>
#include <QHostInfo>
#include <QList>
#include <iostream>
void ARCSNetworkServerThread::run()
......@@ -30,33 +31,38 @@ void ARCSNetworkServerThread::handleRequest(QTcpSocket* socket)
return ;
}
switch(request->getType())
if (request->getType() == ARCSNetworkFrame::CALL_REQUEST)
{
case ARCSNetworkFrame::CONNECT_REQUEST :
handleConnectRequest((ARCSNetworkConnectRequest*)request->getData(), socket);
break;
case ARCSNetworkFrame::CALL_REQUEST :
handleCallRequest((ARCSNetworkCallRequest*)request->getData(), socket);
break;
case ARCSNetworkFrame::SLOT_REQUEST :
handleSlotRequest((ARCSNetworkSlotRequest*)request->getData(), socket);
break;
case ARCSNetworkFrame::SIGNAL_REQUEST :
handleSignalRequest((ARCSNetworkSignalRequest*)request->getData(), socket);
break;
case ARCSNetworkFrame::DISCONNECT_REQUEST :
handleDisconnectRequest((ARCSNetworkDisconnectRequest*)request->getData(), socket);
break;
case ARCSNetworkFrame::IFACE_REQUEST :
handleInterfaceRequest(socket);
break;
default:
;
};
}
else
{
if (!checkInterface(socket))
return;
switch(request->getType())
{
case ARCSNetworkFrame::CONNECT_REQUEST :
handleConnectRequest((ARCSNetworkConnectRequest*)request->getData(), socket);
break;
case ARCSNetworkFrame::SLOT_REQUEST :
handleSlotRequest((ARCSNetworkSlotRequest*)request->getData(), socket);
break;
case ARCSNetworkFrame::SIGNAL_REQUEST :
handleSignalRequest((ARCSNetworkSignalRequest*)request->getData(), socket);
break;
case ARCSNetworkFrame::DISCONNECT_REQUEST :
handleDisconnectRequest((ARCSNetworkDisconnectRequest*)request->getData(), socket);
break;
case ARCSNetworkFrame::IFACE_REQUEST :
handleInterfaceRequest(socket);
break;
default:
;
}
}
// 3 deconnexion
socket->disconnectFromHost();
delete request;
......@@ -74,7 +80,7 @@ void ARCSNetworkServerThread::handleConnectRequest(ARCSNetworkConnectRequest* an
if (!socketDest->waitForConnected(ARCSNetworkFrame::TimeOut))
{
ARCS::Network::logError(417,socketDest->errorString());
//! \todo return error frame
sendErrorFrame(11,socket);
return ;
}
......@@ -83,8 +89,8 @@ void ARCSNetworkServerThread::handleConnectRequest(ARCSNetworkConnectRequest* an
((ARCSNetworkSlotRequest*)request.getData())->setSlot(ancr->getSlot());
if (!request.writeFrame(socketDest.data()))
{
ARCS::Network::logError(419,socketDest->errorString());
//! \todo return error frame
ARCS::Network::logError(419,socketDest->errorString());
sendErrorFrame(12,socket);
return;
}
......@@ -93,21 +99,35 @@ void ARCSNetworkServerThread::handleConnectRequest(ARCSNetworkConnectRequest* an
if (response )
{
if (response->getType() != ARCSNetworkFrame::SLOT_RESPONSE)
//! \todo process if it is an error frame
{
ARCS::Network::logError(486);
if (response->getType() == ARCSNetworkFrame::ERR_RESPONSE)
{
sendErrorFrame(((ARCSNetworkErrResponse*)response->getData())->getErrId()-10,socket);
delete response;
return ;
}
}
else
id = ((ARCSNetworkSlotResponse*)response->getData())->getId();
delete response;
}
else
{
ARCS::Network::logError(488);
sendErrorFrame(14,socket);
return ;
}
if (response)
delete response;
// 2 : creation du stub :
//! \todo create slot stub fails sometimes we should be able to forward error messages
ARCSNetworkServer::getInstance()->createSlotStub(ancr->getSignal(),id,portDest,hostDest);
if (ARCSNetworkServer::getInstance()->createSlotStub(ancr->getSignal(),id,portDest,hostDest) < 0)
{
sendErrorFrame(26,socket);
return;
}
// 3 : ack : c'est fini !
ARCSNetworkFrame frame(ARCSNetworkFrame::ACK_RESPONSE);
......@@ -115,16 +135,40 @@ void ARCSNetworkServerThread::handleConnectRequest(ARCSNetworkConnectRequest* an
ARCS::Network::logError(559,socket->errorString());
}
bool ARCSNetworkServerThread::checkInterface(QTcpSocket *socket)
{
if (!ARCSNetworkServer::getInstance()->isBound())
{
sendErrorFrame(10,socket);
return false;
}
return true;
}
void ARCSNetworkServerThread::handleSlotRequest(ARCSNetworkSlotRequest* ansr, QTcpSocket* socket)
void ARCSNetworkServerThread::sendErrorFrame(int errId, QTcpSocket *socket)
{
ARCS::Network::logError(errId," ");
ARCSNetworkFrame frame(ARCSNetworkFrame::ERR_RESPONSE);
((ARCSNetworkErrResponse*)frame.getData())->setErrId(errId);
if (!frame.writeFrame(socket))
ARCS::Network::logError(599,socket->errorString());
}
void ARCSNetworkServerThread::handleSlotRequest(
ARCSNetworkSlotRequest* ansr, QTcpSocket* socket)
{
int id = -1;
//! \todo do something in case createSignalStub fails
id = ARCSNetworkServer::getInstance()->createSignalStub(ansr->getSlot());
ARCSNetworkFrame frame(ARCSNetworkFrame::SLOT_RESPONSE);
((ARCSNetworkSlotResponse*)frame.getData())->setId(id);
if (!frame.writeFrame(socket))
ARCS::Network::logError(589,socket->errorString());
if ( (id = ARCSNetworkServer::getInstance()->createSignalStub(ansr->getSlot())) >= 0 )
{
ARCSNetworkFrame frame(ARCSNetworkFrame::SLOT_RESPONSE);
((ARCSNetworkSlotResponse*)frame.getData())->setId(id);
if (!frame.writeFrame(socket))
ARCS::Network::logError(589,socket->errorString());
}
else
sendErrorFrame(25,socket);
}
......@@ -141,7 +185,8 @@ void ARCSNetworkServerThread::handleInterfaceRequest(QTcpSocket* socket)
}
void ARCSNetworkServerThread::handleDisconnectRequest(ARCSNetworkDisconnectRequest* andr, QTcpSocket* socket)
void ARCSNetworkServerThread::handleDisconnectRequest(
ARCSNetworkDisconnectRequest* andr, QTcpSocket* socket)
{
ARCSNetworkServer::getInstance()->destroySlotStub(andr->getSignal());
//! \todo do something in case destroyslotstub fails
......@@ -151,26 +196,33 @@ void ARCSNetworkServerThread::handleDisconnectRequest(ARCSNetworkDisconnectReque
}
void ARCSNetworkServerThread::handleSignalRequest(ARCSNetworkSignalRequest* ansr, QTcpSocket* socket)
void ARCSNetworkServerThread::handleSignalRequest(
ARCSNetworkSignalRequest* ansr, QTcpSocket* socket)
{
ARCSNetworkServer::getInstance()->createSlotStub(ansr->getSignal(),
ansr->getId(),
ansr->getPort(),
socket->peerAddress().toString());
//! \todo do something in case createslotstub fails
ARCSNetworkFrame frame(ARCSNetworkFrame::ACK_RESPONSE);
if (! frame.writeFrame(socket))
ARCS::Network::logError(559,socket->errorString());
if (ARCSNetworkServer::getInstance()->createSlotStub(
ansr->getSignal(), ansr->getId(), ansr->getPort(),
socket->peerAddress().toString()) < 0)
sendErrorFrame(26,socket);
else
{
ARCSNetworkFrame frame(ARCSNetworkFrame::ACK_RESPONSE);
if (! frame.writeFrame(socket))
ARCS::Network::logError(559,socket->errorString());
}
}
void ARCSNetworkServerThread::handleCallRequest(ARCSNetworkCallRequest* ancr, QTcpSocket* socket)
void ARCSNetworkServerThread::handleCallRequest(
ARCSNetworkCallRequest* ancr, QTcpSocket* socket)
{
ARCSNetworkServer::getInstance()->call(ancr->getId(), ancr->getParams());
//! \todo do something in case call fails.
ARCSNetworkFrame frame(ARCSNetworkFrame::ACK_RESPONSE);
if (! frame.writeFrame(socket))
ARCS::Network::logError(559,socket->errorString());
if (ARCSNetworkServer::getInstance()->call(ancr->getId(), ancr->getParams()))
{
ARCSNetworkFrame frame(ARCSNetworkFrame::ACK_RESPONSE);
if (! frame.writeFrame(socket))
ARCS::Network::logError(559,socket->errorString());
}
else
sendErrorFrame(27,socket);
}
/*****************************************************************************/
......@@ -208,7 +260,8 @@ void ARCSNetworkServer::run()
else
{
port = i;
ARCS::Network::logInformation("Listening to port" + QString::number(port));
ARCS::Network::logInformation(
"Listening to port " + QString::number(port));
}
}
else
......@@ -252,14 +305,22 @@ void ARCSNetworkServer::startServer()
}
void ARCSNetworkServer::call(int id, QStringList params)
bool ARCSNetworkServer::call(int id, QStringList params)
{
if (proxySignals.count() > id)
{
proxySignals[id]->call(params);
if (!proxySignals[id]->call(params))
{
ARCS::Network::logError(604,QString::number(id)+" with params "+params.join(" "));
return false;
}
return true;
}
else
{
ARCS::Network::logError(604,QString::number(id)+" with params "+params.join(" "));
return false;
}
}
int ARCSNetworkServer::createSignalStub(QString s)
......@@ -271,20 +332,36 @@ int ARCSNetworkServer::createSignalStub(QString s)
{
ARCSNetworkProxySignal* ans = new ARCSNetworkProxySignal(this);
ans->setSignal(s);
id = proxySignals.count(); //- 1;
proxySignals.append(ans);
id = proxySignals.count() - 1;
proxySignalsMap.insert(s, id);
if (interface)
ARCSAbstractComponent::connect(s,interface, s);
{
if (!ARCSAbstractComponent::connect(s,interface, s))
{
// since it fails, we should remove all from lists
proxySignals.removeAll(ans);
proxySignalsMap.remove(s);
delete ans;
return -1;
}
}
else
{
ARCS::Network::logError(603);
proxySignals.removeAll(ans);
proxySignalsMap.remove(s);
delete ans;
return -1;
}
}
return id;
}
int ARCSNetworkServer::createSlotStub(QString signal, int id, quint16 port,QString peer)
int ARCSNetworkServer::createSlotStub(QString signal, int id, quint16 port,
QString peer)
{
ARCSNetworkProxySlot* ans = new ARCSNetworkProxySlot(this);
ans->setHostname(peer);
......@@ -294,9 +371,21 @@ int ARCSNetworkServer::createSlotStub(QString signal, int id, quint16 port,QStri
proxySlots.insertMulti(signal, ans);
if (interface)
interface->connect(signal, this, signal);
{
if (!interface->connect(signal, this, signal))
{
proxySlots.remove(signal);
delete ans;
return -1;
}
}
else
{
proxySlots.remove(signal);
delete ans;
ARCS::Network::logError(603);
return -1;
}
return 0;
}
......@@ -304,6 +393,9 @@ int ARCSNetworkServer::createSlotStub(QString signal, int id, quint16 port,QStri
void ARCSNetworkServer::destroySlotStub(QString signal)
{
// there is a potential failure since not all proxyslots may be
// connected to the same hosts and may be used in several (possibly
// different) applications
QList<ARCSNetworkProxySlot*> slotList = proxySlots.values(signal);
for (int i=0;i < slotList.count() ; i++)
delete slotList[i];
......@@ -366,7 +458,8 @@ ARCSNetworkServer* ARCSNetworkServer::getInstance()
return instance;
}
void ARCSNetworkServer::getProxySlot (QString slot, ObjectList &obj, QStringList &proxySlot)
void ARCSNetworkServer::getProxySlot(QString slot, ObjectList &obj,
QStringList &proxySlot)
{
QList<ARCSNetworkProxySlot*> anps;
if (proxySlots.contains(slot))
......@@ -381,7 +474,8 @@ void ARCSNetworkServer::getProxySlot (QString slot, ObjectList &obj, QStringList
}
void ARCSNetworkServer::getProxySignal (QString signal, ObjectList &obj, QStringList &proxySignal)
void ARCSNetworkServer::getProxySignal(QString signal, ObjectList &obj,
QStringList &proxySignal)
{
ARCSNetworkProxySignal* anps;
if (proxySignalsMap.contains(signal))
......
......@@ -45,6 +45,8 @@ class ARCSNetworkServerThread : public QThread
void handleSignalRequest(ARCSNetworkSignalRequest* ansr, QTcpSocket* socket);
void handleDisconnectRequest(ARCSNetworkDisconnectRequest* andr, QTcpSocket* socket);
void handleInterfaceRequest(QTcpSocket* socket);
bool checkInterface(QTcpSocket* socket);
void sendErrorFrame(int errId, QTcpSocket* socket);
int socketDescriptor;
......@@ -107,7 +109,7 @@ public:
* \param id id of the slot to call
* \param params serialized parameters of the slot
*/
void call(int id, QStringList params);
bool call(int id, QStringList params);
/*! \brief Creates a signal stub to connect to a slot of the interface
* \param s the name of the slot of the interface
......@@ -124,6 +126,7 @@ public:
*/
int createSlotStub(QString signal, int id, quint16 port, QString peer);
bool isBound() { return interface != 0; }
void destroySlotStub(QString s);
......@@ -154,6 +157,9 @@ protected:
private:
//bool checkInterface();
ARCSNetworkServer();
static ARCSNetworkServer* instance;
bool inEventMode;
......