From a8cd31b9681938b1cea0d02e884962fd8f114208 Mon Sep 17 00:00:00 2001 From: haller Date: Sat, 21 Jan 2006 21:10:23 +0000 Subject: - ajout de quelques structures de données - importation de la class nonCopyable et utilisation dans quelques classes - création d'une class exception simulotron_exception - ajout d'un paramètre "bloquant" pour recevoir une GS - modification de la valeur de retour des fonction servant à récupérer une GS - Mise en place de la poignée de main lors de la connection d'un module au hub - Ajout d'un message template pour les message vide - suppression des fonction (get|put)Char et getFD de la classe socket - modification de la fonction GSMessage::getString à deux arguments - ajout d'un test_hub - ajout de la class ComH (un peu comme ComC mais coté hub) --- i/simulotron/doc/message.txt | 13 +- i/simulotron/src/aiguillage/Makefile.incl.am | 8 ++ i/simulotron/src/aiguillage/aiguillage.cc | 13 +- i/simulotron/src/aiguillage/aiguillage.hh | 5 +- i/simulotron/src/aiguillage/test_aiguillage.cc | 6 +- i/simulotron/src/comc/comc.cc | 29 ++++- i/simulotron/src/comc/comc.hh | 8 +- i/simulotron/src/comc/struct_message.hh | 49 +++++++- i/simulotron/src/comc/test_comc.cc | 2 +- i/simulotron/src/gs/gs_message.cc | 11 +- i/simulotron/src/gs/gs_message.hh | 2 +- i/simulotron/src/gs/gs_transmitter.cc | 72 +++++++---- i/simulotron/src/gs/gs_transmitter.hh | 6 +- i/simulotron/src/gs/test_gs.cc | 14 +-- i/simulotron/src/hub/Makefile.incl.am | 10 ++ i/simulotron/src/hub/comh.cc | 107 ++++++++++++++++ i/simulotron/src/hub/comh.hh | 68 +++++++++++ i/simulotron/src/hub/hub.cc | 44 ++++--- i/simulotron/src/hub/hub.hh | 11 +- i/simulotron/src/hub/test_hub.cc | 162 +++++++++++++++++++++++++ i/simulotron/src/socket/socket_client.cc | 52 ++++---- i/simulotron/src/socket/socket_client.hh | 13 +- i/simulotron/src/socket/socket_server.cc | 10 +- i/simulotron/src/socket/socket_server.hh | 5 +- i/simulotron/src/socket/test_socket.cc | 40 +++--- i/simulotron/src/utils/non_copyable.hh | 41 +++++++ i/simulotron/src/utils/simulotron_exception.hh | 44 +++++++ 27 files changed, 704 insertions(+), 141 deletions(-) create mode 100644 i/simulotron/src/aiguillage/Makefile.incl.am create mode 100644 i/simulotron/src/hub/Makefile.incl.am create mode 100644 i/simulotron/src/hub/comh.cc create mode 100644 i/simulotron/src/hub/comh.hh create mode 100644 i/simulotron/src/hub/test_hub.cc create mode 100644 i/simulotron/src/utils/non_copyable.hh create mode 100644 i/simulotron/src/utils/simulotron_exception.hh (limited to 'i') diff --git a/i/simulotron/doc/message.txt b/i/simulotron/doc/message.txt index 04b6cfb..8d6398b 100644 --- a/i/simulotron/doc/message.txt +++ b/i/simulotron/doc/message.txt @@ -56,4 +56,15 @@ Une derni * Annexe : Table des structures -Pas de structure pour l'instant + !--------------------------------------------------------!------------------------------------------------------! + !n° ! description ! contenu ! + !-----!--------------------------------------------------!------------------------------------------------------! + ! 0 ! message de test ! int i ! + ! ! ! double d ! + ! ! ! std::string strh (8 char) ! + ! ! ! short s ! + ! ! ! std::string str ! + ! ! ! long l ! + ! 1 ! premier message d'init entre un module et le hub ! std::string moduleName // contient le nom du module ! + ! 2 ! message d'ack du hub au module se connectant ! ! + !-----!--------------------------------------------------!------------------------------------------------------! diff --git a/i/simulotron/src/aiguillage/Makefile.incl.am b/i/simulotron/src/aiguillage/Makefile.incl.am new file mode 100644 index 0000000..0b589d6 --- /dev/null +++ b/i/simulotron/src/aiguillage/Makefile.incl.am @@ -0,0 +1,8 @@ +aiguillage_S = aiguillage/aiguillage.cc aiguillage/aiguillage.hh + +check_PROGRAMS += test_aiguillage +test_aiguillage_SOURCES = aiguillage/test_aiguillage.cc \ + $(aiguillage_S) \ + $(gs_message_S) \ + $(gs_transmitter_S) \ + $(socket_S) diff --git a/i/simulotron/src/aiguillage/aiguillage.cc b/i/simulotron/src/aiguillage/aiguillage.cc index 6292ce7..3abd5ab 100644 --- a/i/simulotron/src/aiguillage/aiguillage.cc +++ b/i/simulotron/src/aiguillage/aiguillage.cc @@ -25,6 +25,7 @@ #include "aiguillage/aiguillage.hh" #include "gs/gs_message.hh" +#include "utils/simulotron_exception.hh" #include @@ -59,25 +60,25 @@ Aiguillage::send(const GSMessage & gsm, const std::string & source, } /// Reçoie un paquet du réseau et supprime les infos src et dest du GSM -int -Aiguillage::receive(GSMessage & gsm, std::string & source, std::string & dest) +bool +Aiguillage::receive(GSMessage & gsm, std::string & source, std::string & dest, bool bloquant) { std::string tmp; - if(gst_.getGS(gsm) != 0) - return -1; + if(!gst_.getGS(gsm, bloquant)) + return false; gsm.getString(tmp, 8); source = tmp.c_str(); gsm.getString(tmp, 8); dest = tmp.c_str(); gsm.delBeforeIt(); - return 0; + return true; } void Aiguillage::setName(const std::string & name) { if(name.size() > MAX_SIZE_NAME) - throw std::runtime_error("Le nom est trop long!!"); + throw simulotron_exception("Aiguillage", "Le nom est trop long!!"); name_ = name; name_.append(MAX_SIZE_NAME - name.size(), '\0'); } diff --git a/i/simulotron/src/aiguillage/aiguillage.hh b/i/simulotron/src/aiguillage/aiguillage.hh index bdfc8a0..8f7eaf1 100644 --- a/i/simulotron/src/aiguillage/aiguillage.hh +++ b/i/simulotron/src/aiguillage/aiguillage.hh @@ -26,8 +26,9 @@ * }}} */ #include "gs/gs_transmitter.hh" +#include "utils/non_copyable.hh" -class Aiguillage +class Aiguillage : public NonCopyable { private: static const unsigned int MAX_SIZE_NAME = 8; @@ -42,7 +43,7 @@ class Aiguillage /// Envoie un paquet en rajoutant les infos de sources et de provenance void send(const GSMessage & gsm, const std::string & source, const std::string & dest); /// Reçoie un paquet du réseau et supprime les infos src et dest du GSM - int receive(GSMessage & gsm, std::string & source, std::string & dest); + bool receive(GSMessage & gsm, std::string & source, std::string & dest, bool bloquant); private: /// Set le nom de transmition void setName(const std::string & name); diff --git a/i/simulotron/src/aiguillage/test_aiguillage.cc b/i/simulotron/src/aiguillage/test_aiguillage.cc index 36285f8..bb65af0 100644 --- a/i/simulotron/src/aiguillage/test_aiguillage.cc +++ b/i/simulotron/src/aiguillage/test_aiguillage.cc @@ -82,7 +82,7 @@ int testGSServer(SocketServer & sockServ) // Reception des messages GSMessage gsm; // Message 1 - while (aiSNCF.receive(gsm, source, dest) != 0); + while (!aiSNCF.receive(gsm, source, dest, true)); gsm.readGS(&i2, sizeof(int)); if (i1 != i2) { @@ -110,7 +110,7 @@ int testGSServer(SocketServer & sockServ) } gsm.clear(); // Message 2 - while (aiSNCF.receive(gsm, source, dest) != 0); + while (!aiSNCF.receive(gsm, source, dest, true)); gsm.readGS(&i2, sizeof(int)); if (i1 != i2) { @@ -138,7 +138,7 @@ int testGSServer(SocketServer & sockServ) } gsm.clear(); // Message 3 - while (aiSNCF.receive(gsm, source, dest) != 0); + while (!aiSNCF.receive(gsm, source, dest, true)); gsm.readGS(&i2, sizeof(int)); if (i1 != i2) { diff --git a/i/simulotron/src/comc/comc.cc b/i/simulotron/src/comc/comc.cc index cbfb474..6ac3f69 100644 --- a/i/simulotron/src/comc/comc.cc +++ b/i/simulotron/src/comc/comc.cc @@ -30,7 +30,7 @@ /// Constructeur client ComC::ComC(const std::string & address, int port, const std::string & name) - :aiguillage_(address, port, name) + :aiguillage_(address, port, name), moduleName_(name) { } @@ -40,6 +40,23 @@ ComC::ComC(SocketServer & socket, const std::string & name) { } +/// Initialise la communication avec le hub +void +ComC::initHub(void) +{ + // Envoie du premier message + msg1 ms; + ms.moduleName = moduleName_; + send(ms,std::string("hub")); + // Attente de la reponse du hub + GSMessage gsm; + std::string source, dest; + int msgId; + receiveGS(gsm, source, dest, msgId, true); + if (msgId != 2) /// \todo c'est moche + throw simulotron_exception("ComC:", "Rejet du hub!!"); +} + void ComC::send(const msgX & message, const std::string & destname) { @@ -49,13 +66,13 @@ ComC::send(const msgX & message, const std::string & destname) } /// Récupération de la GS -int -ComC::receiveGS(GSMessage & gsm, std::string & source, std::string & dest, int & msgId) +bool +ComC::receiveGS(GSMessage & gsm, std::string & source, std::string & dest, int & msgId, bool bloquant) { - if(aiguillage_.receive(gsm, source, dest) != 0) - return 1; + if(!aiguillage_.receive(gsm, source, dest, bloquant)) + return false; gsm.readGS(&msgId, sizeof(int)); gsm.setIteratorBegin(); - return 0; + return true; } diff --git a/i/simulotron/src/comc/comc.hh b/i/simulotron/src/comc/comc.hh index a7e0076..4650329 100644 --- a/i/simulotron/src/comc/comc.hh +++ b/i/simulotron/src/comc/comc.hh @@ -27,22 +27,24 @@ #include "aiguillage/aiguillage.hh" #include "comc/struct_message.hh" +#include "utils/non_copyable.hh" -class ComC +class ComC : public NonCopyable { private: Aiguillage aiguillage_; + std::string moduleName_; public: /// Constructeur client ComC(const std::string & address, int port, const std::string & name); /// Constructeur serveur ComC(SocketServer & socket, const std::string & name); /// Initialise la communication avec le hub - void InitHub(void); + void initHub(void); /// Envoie un truc dans le réseau void send(const msgX & message, const std::string & destname); /// Récupération de la GS - int receiveGS(GSMessage & gsm, std::string & source, std::string & dest, int & msgId); + bool receiveGS(GSMessage & gsm, std::string & source, std::string & dest, int & msgId, bool bloquant); }; #endif //COMC_HH diff --git a/i/simulotron/src/comc/struct_message.hh b/i/simulotron/src/comc/struct_message.hh index 598ac40..316393e 100644 --- a/i/simulotron/src/comc/struct_message.hh +++ b/i/simulotron/src/comc/struct_message.hh @@ -26,6 +26,7 @@ * }}} */ #include "gs/gs_message.hh" +#include "utils/simulotron_exception.hh" #include #include @@ -38,6 +39,7 @@ struct msgX virtual void gsToMsg(GSMessage & gsm) = 0; }; +/// Message 0: message de test, aucune utilité struct msg0 : public msgX { int i; @@ -66,7 +68,7 @@ struct msg0 : public msgX int tmp; gsm.readGS(&tmp, sizeof(int)); if(tmp != msgId) - throw std::runtime_error("la gs ne correspond pas à la structure"); + throw simulotron_exception("msg0", "la gs ne correspond pas à la structure"); gsm.readGS(&i, sizeof(int)); gsm.readGS(&d, sizeof(double)); gsm.getString(strh, 8); @@ -76,4 +78,49 @@ struct msg0 : public msgX } }; +/// Message 1: initialisation de la com module/hub, premier message +struct msg1 : public msgX +{ + std::string moduleName; //8 char + + virtual void msgToGs(GSMessage & gsm) const + { + int msgId = 1; + gsm.clear(); + gsm.appendGS(&msgId, sizeof(int)); + gsm.appendGS(moduleName.data(), 8); + } + + virtual void gsToMsg(GSMessage & gsm) + { + int msgId = 1; + int tmp; + gsm.readGS(&tmp, sizeof(int)); + if(tmp != msgId) + throw simulotron_exception("msg1", "la gs ne correspond pas à la structure"); + gsm.getString(moduleName, 8); + } +}; + +/// Message ?: template pour les messages vide +template +struct msg : public msgX +{ + virtual void msgToGs(GSMessage & gsm) const + { + int msgId = MSGID; + gsm.clear(); + gsm.appendGS(&msgId, sizeof(int)); + } + virtual void gsToMsg(GSMessage & gsm) + { + int msgId = MSGID; + int tmp; + gsm.readGS(&tmp, sizeof(int)); + if(tmp != msgId) + throw simulotron_exception("msg" + MSGID, "la gs ne correspond pas à la structure"); + } +}; + + #endif //STRUCT_MESSAGE_HH diff --git a/i/simulotron/src/comc/test_comc.cc b/i/simulotron/src/comc/test_comc.cc index 7182df1..90d2119 100644 --- a/i/simulotron/src/comc/test_comc.cc +++ b/i/simulotron/src/comc/test_comc.cc @@ -87,7 +87,7 @@ int testGSServer(SocketServer & sockServ) int msgId; // Création de la comc ComC comc(sockServ,"serveur"); - while(comc.receiveGS(gsm,source,dest, msgId)){} + while(!comc.receiveGS(gsm,source,dest, msgId, true)){} mscom.gsToMsg(gsm); if(!(ms.i == mscom.i && ms.d == mscom.d && diff --git a/i/simulotron/src/gs/gs_message.cc b/i/simulotron/src/gs/gs_message.cc index 0ab8bb8..df37ca0 100644 --- a/i/simulotron/src/gs/gs_message.cc +++ b/i/simulotron/src/gs/gs_message.cc @@ -25,6 +25,7 @@ #include "gs/gs_message.hh" #include "gs/gs_transmitter.hh" +#include "utils/simulotron_exception.hh" #include @@ -33,9 +34,9 @@ GSMessage::GSMessage(void) { } -GSMessage::GSMessage(GSTransmitter & gst) +GSMessage::GSMessage(GSTransmitter & gst, bool bloquant) { - gst.getGS(*this); + gst.getGS(*this, bloquant); } const std::string & @@ -50,7 +51,7 @@ GSMessage::readGS(void * data, size_t size) std::string str; str.assign(igs_, gs_.end()); if (size > str.size()) - throw std::runtime_error("CHIER!!! La size dans readGS est trop grande!!"); + throw simulotron_exception("GSMessage:", "CHIER!!! La size dans readGS est trop grande!!"); memcpy(data, str.data(), size); igs_ += size; } @@ -66,7 +67,11 @@ GSMessage::getString(std::string & str) void GSMessage::getString(std::string & str, size_t size) { + unsigned int pos0; str.assign(igs_, igs_ + size); + pos0 = str.find('\0'); + if (pos0 != std::string::npos) + str.erase(pos0); igs_ += size; } diff --git a/i/simulotron/src/gs/gs_message.hh b/i/simulotron/src/gs/gs_message.hh index cfb0b41..b970571 100644 --- a/i/simulotron/src/gs/gs_message.hh +++ b/i/simulotron/src/gs/gs_message.hh @@ -39,7 +39,7 @@ class GSMessage /// Constructeur sans argument GSMessage (void); /// Constructeur/récupérateur - GSMessage (GSTransmitter & gst); + GSMessage (GSTransmitter & gst, bool bloquant); /// Récupération de la string en entier const std::string & getGS (void) const; /// Récupération de données de la gs diff --git a/i/simulotron/src/gs/gs_transmitter.cc b/i/simulotron/src/gs/gs_transmitter.cc index 9f53963..abdfd0f 100644 --- a/i/simulotron/src/gs/gs_transmitter.cc +++ b/i/simulotron/src/gs/gs_transmitter.cc @@ -40,40 +40,60 @@ GSTransmitter::GSTransmitter(const std::string & address, int port) socket_.connect(address, port); } -/// Renvoie 0 quand un message est récupéré, -1 sinon -int -GSTransmitter::getGS(GSMessage & gsm) +/// Renvoie true quand un message est récupéré, false sinon +bool +GSTransmitter::getGS(GSMessage & gsm, bool bloquant) { ///\bug Pas portable le code, suppose des int à 4 octect - fd_set fds; - timeval tv = {0, 0}; unsigned int size = 0; + bool GSCompleted; - FD_ZERO(&fds); - FD_SET(socket_.getFD(), &fds); - //On lit le socket que si y'a quelque chose à lire - ///\bug C'est top ca? - if(select(socket_.getFD() + 1, &fds, NULL, NULL, &tv) > 0) + do { - std::string strRead (socket_.read ()); + GSCompleted = true; + std::string strRead; + socket_.read(strRead, bloquant); strBrut_ += strRead; - } - // Si la chaine à moins de 4 octect, y'a pas de message - if (strBrut_.size() < 4) - return -1; - // On récupère la taille de la gs grace au 4 premier octect - size = static_cast (strBrut_[0]) << 24 - | static_cast (strBrut_[1]) << 16 - | static_cast (strBrut_[2]) << 8 - | static_cast (strBrut_[3]); - if(size > strBrut_.size() - 4) - return -1; - gsm.appendGS (strBrut_.substr(4, size).data(), size); - strBrut_.erase (0, size + 4); - return 0; + // Si la chaine à moins de 4 octect, y'a pas de message + if (strBrut_.size() < 4) + { + if(!bloquant) + return false; + else + GSCompleted = false; + } + }while (!GSCompleted); + do + { + GSCompleted = true; + + // On récupère la taille de la gs grace au 4 premier octect + size = static_cast (strBrut_[0]) << 24 + | static_cast (strBrut_[1]) << 16 + | static_cast (strBrut_[2]) << 8 + | static_cast (strBrut_[3]); + if(size > strBrut_.size() - 4) + { + if(!bloquant) + return false; + else + GSCompleted = false; + } + else + { + gsm.clear(); + gsm.appendGS (strBrut_.substr(4, size).data(), size); + strBrut_.erase (0, size + 4); + return true; + } + std::string strRead; + socket_.read(strRead, bloquant); + strBrut_ += strRead; + }while (!GSCompleted); + return true; } -void + void GSTransmitter::putGS(const GSMessage & gsm) { ///\bug Pas portable le code, suppose des int à 4 octect diff --git a/i/simulotron/src/gs/gs_transmitter.hh b/i/simulotron/src/gs/gs_transmitter.hh index 86c0620..03b01e9 100644 --- a/i/simulotron/src/gs/gs_transmitter.hh +++ b/i/simulotron/src/gs/gs_transmitter.hh @@ -26,12 +26,14 @@ * }}} */ #include "socket/socket_client.hh" +#include "utils/non_copyable.hh" + #include class SocketServer; class GSMessage; -class GSTransmitter +class GSTransmitter : public NonCopyable { private: /// Socket de transmission @@ -44,7 +46,7 @@ class GSTransmitter /// Constructeur prenant une adresse (cas d'un client) GSTransmitter(const std::string & address, int port); /// Récupère une grosse string - int getGS(GSMessage & gsm); + bool getGS(GSMessage & gsm, bool bloquant); /// envoie une grosse string void putGS(const GSMessage & gsm); }; diff --git a/i/simulotron/src/gs/test_gs.cc b/i/simulotron/src/gs/test_gs.cc index acf47f9..c9e9ea5 100644 --- a/i/simulotron/src/gs/test_gs.cc +++ b/i/simulotron/src/gs/test_gs.cc @@ -89,7 +89,7 @@ int testGSServer(SocketServer & sockServ) // Reception des messages // une string GSMessage gsm; - while (gst.getGS(gsm) != 0); + while (!gst.getGS(gsm,true)); gsm.getString(strDest); if (strDepart != strDest) { @@ -101,7 +101,7 @@ int testGSServer(SocketServer & sockServ) } gsm.clear(); // Un char - while (gst.getGS(gsm) != 0); + while (!gst.getGS(gsm, true)); gsm.readGS(&b, sizeof(char)); if ( a != b) { @@ -113,7 +113,7 @@ int testGSServer(SocketServer & sockServ) } gsm.clear(); // Un short - while (gst.getGS(gsm) != 0); + while (!gst.getGS(gsm, true)); gsm.readGS(&s2, sizeof(short)); if ( s1 != s2) { @@ -125,7 +125,7 @@ int testGSServer(SocketServer & sockServ) } gsm.clear(); // Un int positif - while (gst.getGS(gsm) != 0); + while (!gst.getGS(gsm, true)); gsm.readGS(&i2, sizeof(int)); if ( i1 != i2) { @@ -137,7 +137,7 @@ int testGSServer(SocketServer & sockServ) } gsm.clear(); // Un int negatif - while (gst.getGS(gsm) != 0); + while (!gst.getGS(gsm, true)); gsm.readGS(&i4, sizeof(int)); if ( i3 != i4) { @@ -149,7 +149,7 @@ int testGSServer(SocketServer & sockServ) } gsm.clear(); // Un Long - while (gst.getGS(gsm) != 0); + while (!gst.getGS(gsm, true)); gsm.readGS(&l2, sizeof(long)); if ( l1 != l2) { @@ -161,7 +161,7 @@ int testGSServer(SocketServer & sockServ) } gsm.clear(); // Un gros message - while (gst.getGS(gsm) != 0); + while (!gst.getGS(gsm, true)); gsm.readGS(&s2,sizeof(short)); gsm.readGS(&l2,sizeof(long)); gsm.getString(strDest); diff --git a/i/simulotron/src/hub/Makefile.incl.am b/i/simulotron/src/hub/Makefile.incl.am new file mode 100644 index 0000000..6100bc4 --- /dev/null +++ b/i/simulotron/src/hub/Makefile.incl.am @@ -0,0 +1,10 @@ +hub_S = hub/hub.cc hub/hub.hh hub/comh.cc hub/comh.hh + +check_PROGRAMS += test_hub +test_hub_SOURCES = hub/test_hub.cc \ + $(hub_S) \ + $(comc_S) \ + $(gs_message_S) \ + $(socket_S) \ + $(aiguillage_S) \ + $(gs_transmitter_S) diff --git a/i/simulotron/src/hub/comh.cc b/i/simulotron/src/hub/comh.cc new file mode 100644 index 0000000..124238e --- /dev/null +++ b/i/simulotron/src/hub/comh.cc @@ -0,0 +1,107 @@ +/* comh.cc - Classe ComC speciale Hub */ +/* Simulotron - Programme de simulation de robot {{{ + * + * Copyright (C) 2006 Nicolas Haller + * + * Robot APB Team/Efrei 2005. + * Web: http://assos.efrei.fr/robot/ + * Email: robot AT efrei DOT fr + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * }}} */ + +#include "hub/comh.hh" +#include "gs/gs_message.hh" +#include "comc/struct_message.hh" + +#include + +ComH::ComH (SocketServer & socket) + :aiguillage_(socket, std::string("hub")), waitingForMessage_(false) +{ + initCom(); +} + +const std::string & +ComH::getModuleName(void) +{ + return moduleName_; +} + +bool +ComH::receiveMsg(GSMessage & gsm, std::string & source, std::string & dest, int & msgId, bool bloquant) +{ + if(aiguillage_.receive(gsm, source , dest, bloquant)) + { + gsm.readGS(&msgId, sizeof(int)); + gsm.setIteratorBegin(); + return true; + } + return false; +} + +void +ComH::send(const GSMessage & gsm, const std::string & source, const std::string & dest) +{ + aiguillage_.send(gsm, source, dest); +} + +void +ComH::setWait(long long int DL, bool waitingForMessage) +{ + if(isWaiting()) + throw simulotron_exception("ComH", "Le module est déjà en attente!!"); + if(DL <= 0 && !waitingForMessage) + throw simulotron_exception("ComH", "On attend rien là!!"); + dlWaiting_ = DL; + waitingForMessage_ = waitingForMessage; +} + +bool +ComH::isWaiting (void) +{ + if ( waitingForMessage_ || dlWaiting_ > 0) + return true; + return false; +} + +long long int +ComH::getDLWait(void) +{ + return dlWaiting_; +} + +void +ComH::unlockWait(void) +{ + waitingForMessage_ = false; + dlWaiting_ = 0; +} + +void +ComH::initCom(void) +{ + msg1 ms; + GSMessage gsm; + std::string source, dest; + int msgId; + // Reçoit le premier message + receiveMsg(gsm, source, dest, msgId, true); + if(msgId != 1) + throw simulotron_exception("ComH", "initCom: le message de reponse est incorrect!!"); + ms.gsToMsg(gsm); + moduleName_ = ms.moduleName; +} diff --git a/i/simulotron/src/hub/comh.hh b/i/simulotron/src/hub/comh.hh new file mode 100644 index 0000000..b7a938d --- /dev/null +++ b/i/simulotron/src/hub/comh.hh @@ -0,0 +1,68 @@ +#ifndef COMH_HH +#define COMH_HH +/* comh.hh - Class ComC spéciale Hub */ +/* Simulotron - Programme de simulation de robot {{{ + * + * Copyright (C) 2006 Nicolas Haller + * + * Robot APB Team/Efrei 2006. + * Web: http://assos.efrei.fr/robot/ + * Email: robot AT efrei DOT fr + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * }}} */ + +#include "aiguillage/aiguillage.hh" +#include "utils/non_copyable.hh" + +#include + +class SocketServer; +class GSMessage; + +class ComH : public NonCopyable +{ + private: + /// Aiguillage SNCF + Aiguillage aiguillage_; + /// Nom du module distant + std::string moduleName_; + /// En attente d'un message + bool waitingForMessage_; + /// DL du wait + long long int dlWaiting_; + public: + /// Constructeur serveur + ComH (SocketServer & socket); + /// Initialise la com avec le module + void initCom(void); + /// Récupère le nom du module + const std::string & getModuleName(void); + /// Reçoit un message du module + bool receiveMsg(GSMessage & gsm, std::string & source, std::string & dest, int & msgId, bool bloquant); + /// Envoie un message + void send(const GSMessage & gsm, const std::string & source, const std::string & dest); + /// Set un wait(si négatif, le wait est infini) + void setWait(long long int DL, bool waitForMessage); + /// Retourne si le module est en attente + bool isWaiting (void); + /// Retourne la fin de l'attente + long long int getDLWait(void); + /// Delock un module en fin d'attente + void unlockWait (void); +}; + +#endif //COMH_HH diff --git a/i/simulotron/src/hub/hub.cc b/i/simulotron/src/hub/hub.cc index 13d3e23..bfdfc91 100644 --- a/i/simulotron/src/hub/hub.cc +++ b/i/simulotron/src/hub/hub.cc @@ -28,10 +28,17 @@ #include -Hub::Hub (std::string & address, int port) +Hub::Hub (const std::string & address, int port) :timeh_(0), socket_(address, port), isRunning(false) { init(); + socket_.listen(32); +} + +Hub::~Hub(void) +{ + for (std::list::iterator it = modules_.begin(); it != modules_.end(); it++) + delete *it; } void @@ -45,7 +52,9 @@ void Hub::init(void) { // Créer la liste des modules attendus - //dfqsdf + ///\todo faire l'init + modAwaited_.push_back(std::string("module1")); + modAwaited_.push_back(std::string("module2")); } @@ -56,14 +65,15 @@ Hub::waitConnection(void) while (!modAwaited_.empty()) { // On crée le système de com avec le module - modules_.push_back(ComH(socket_)); + modules_.push_back(new ComH(socket_)); // On verifie que le module est attendu - std::list::iterator it = find(modAwaited_.begin(), modAwaited_.end(), modules_.back().getModuleName()); + std::list::iterator it = find(modAwaited_.begin(), modAwaited_.end(), modules_.back()->getModuleName()); if(it == modAwaited_.end()) { // Ouille, on reporte l'incident - std::cerr << "Un module inattendu a tenté de se connecter au Hub, nom du module: " << modules_.back().getModuleName() << std::endl; + std::cerr << "Un module inattendu a tenté de se connecter au Hub, nom du module: " << modules_.back()->getModuleName() << std::endl; // On vire le malotru + delete modules_.back(); modules_.pop_back(); continue; } @@ -87,19 +97,19 @@ Hub::startLoop(void) void Hub::processModules(void) { - for(std::list::iterator it = modules_.begin(); it != modules_.end(); it++) + for(std::list::iterator it = modules_.begin(); it != modules_.end(); it++) { processModule(it); } } void -Hub::processModule(const std::list::iterator & it) +Hub::processModule(const std::list::iterator & it) { std::string source, dest; int msgId; GSMessage gsm; - while (it->receiveMsg(gsm, source, dest, msgId)) + while ((*it)->receiveMsg(gsm, source, dest, msgId, false)) laPoste(gsm, source, dest, msgId); } @@ -108,16 +118,21 @@ Hub::processWaits(void) { int timeToSet = 0; long long int tmp; - for(std::list::iterator it = modules_.begin(); it != modules_.end(); it++) + for(std::list::iterator it = modules_.begin(); it != modules_.end(); it++) { - if(!it->isWaiting()) + if(!(*it)->isWaiting()) return; - tmp = it->getDLWait(); + tmp = (*it)->getDLWait(); if(tmp != -1 && tmp < timeToSet) timeToSet = tmp; } } +void +Hub::processStoppingRules (void) +{ +} + void Hub::laPoste (const GSMessage & gsm, const std::string & source, const std::string & dest, int msgId) { @@ -129,11 +144,10 @@ Hub::laPoste (const GSMessage & gsm, const std::string & source, const std::stri else { ///\todo pas optimisé - for(std::list::iterator it = modules_.begin(); it != modules_.end(); it++) + for(std::list::iterator it = modules_.begin(); it != modules_.end(); it++) { - if(dest == it->getModuleName()) - it->send(gsm, source, dest, msgId); + if(dest == (*it)->getModuleName()) + (*it)->send(gsm, source, dest); } } } - diff --git a/i/simulotron/src/hub/hub.hh b/i/simulotron/src/hub/hub.hh index e91f8d0..318877d 100644 --- a/i/simulotron/src/hub/hub.hh +++ b/i/simulotron/src/hub/hub.hh @@ -27,18 +27,19 @@ #include "hub/comh.hh" #include "socket/socket_server.hh" +#include "utils/non_copyable.hh" #include class GSMessage; -class Hub +class Hub : public NonCopyable { private: /// Horloge de simulation long long int timeh_; /// Listes des modules conectées au hub - std::list modules_; + std::list modules_; /// Socket serveur pour la connection SocketServer socket_; /// Liste des modules attendu @@ -47,7 +48,9 @@ class Hub bool isRunning; public: /// Constructeur - Hub(std::string & address, int port); + Hub(const std::string & address, int port); + /// Destructeur + ~Hub(void); /// Lancement du hub void start(void); private: @@ -60,7 +63,7 @@ class Hub /// Traite les messages des modules void processModules(void); /// Traite les message d'un modules - void processModule(const std::list::iterator & it); + void processModule(const std::list::iterator & it); /// Traite les wait des modules et fait avancer l'horloge si besoin void processWaits(void); /// Traite les règles d'arret du Hub diff --git a/i/simulotron/src/hub/test_hub.cc b/i/simulotron/src/hub/test_hub.cc new file mode 100644 index 0000000..c9645d0 --- /dev/null +++ b/i/simulotron/src/hub/test_hub.cc @@ -0,0 +1,162 @@ +/* test_hub.cc - Programme de test du hub. */ +/* Simulotron - Programme de simulation de robot {{{ + * + * Copyright (C) 2006 Nicolas Haller + * + * Robot APB Team/Efrei 2005. + * Web: http://assos.efrei.fr/robot/ + * Email: robot AT efrei DOT fr + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * }}} */ + +#include "comc/struct_message.hh" +#include "hub/hub.hh" +#include "socket/socket_server.hh" +#include "comc/comc.hh" + +#include +#include +#include + +// message de test +msg0 ms1, ms2; + +int testHub(Hub & hub); +void testModule1(int pauseMode1); +void testModule2(int pauseMode2); + +int main(void) +{ + //pauseMode pour debbuger le fork + int pauseMode1 = 0; + int pauseMode2 = 0; + pid_t pidModule1, pidModule2; + //retour des test + int resultHub, resultModule1, resultModule2; + //Initialisation des valeurs de la struct de test + ms1.i = 42; + ms1.d = 23.23; + ms1.strh = "chier!!!"; + ms1.s = 4; + ms1.str = "Ho!! Une structure de test, comme c'est amusant!!"; + ms1.l = 3432; + // Création du hub + Hub hub(std::string(), 4242); + // On crée le fork du module1 + pidModule1 = fork(); + if (pidModule1 == 0) // processus fils + testModule1(pauseMode1); + else //processus père + { + pidModule2 = fork(); + if (pidModule2 == 0) + testModule2(pauseMode2); + else + resultHub = testHub(hub); + + // On analyse les résultats + waitpid(pidModule1, &resultModule1, 0); + waitpid(pidModule2, &resultModule2, 0); + if (!(WIFEXITED(resultModule1) && WEXITSTATUS(resultModule1) == 0)) + { + std::cerr << "ECHEC: Problème coté module 1" << std::endl; + exit (-1); + } + if (!(WIFEXITED(resultModule2) && WEXITSTATUS(resultModule2) == 0)) + { + std::cerr << "ECHEC: Problème coté module 2" << std::endl; + exit (-1); + } + if (resultHub != 0) + { + std::cerr << "ECHEC: Problème coté hub" << std::endl; + exit (-1); + } + } + return 0; +} + +int testHub(Hub & hub) +{ + try + { + hub.start(); + } + catch (std::exception & c) + { + std::cout << "Oops, exeption dans le hub" << std::endl; + std::cout << c.what() << std::endl; + } + return 0; +} + +void testModule1(int pauseMode) +{ + while(pauseMode) + sleep (10); + try + { + // Création du comc + ComC comc(std::string("127.0.0.1"), 4242, "module1"); + // Initialisation de la com avec le hub + comc.initHub(); + comc.send(ms1, std::string("module2")); + } + catch(std::exception & chier) + { + std::cout << "CHIER !! Une exception a été lancé coté module1!!" << std::endl; + std::cout << chier.what() << std::endl; + exit (1); + } + exit (0); +} + +void testModule2(int pauseMode) +{ + while(pauseMode) + sleep (10); + try + { + GSMessage gsm; + std::string source, dest; + int msgId; + // Création du comc + ComC comc(std::string("127.0.0.1"), 4242, "module2"); + // Initialisation de la com avec le hub + comc.initHub(); + // Reception du message + comc.receiveGS(gsm, source, dest, msgId, true); + ms2.gsToMsg(gsm); + // Test dessus + if (ms1.i != ms2.i || + ms1.d != ms2.d || + ms1.strh != ms2.strh || + ms1.s != ms2.s || + ms1.str != ms2.str || + ms1.l != ms2.l) + { + std::cerr << "CHIER!! Le message n'est pas identique à l'arrivé!!" << std::endl; + } + } + catch(std::exception & chier) + { + std::cout << "CHIER !! Une exception a été lancé coté module2!!" << std::endl; + std::cout << chier.what() << std::endl; + exit (1); + } + exit (0); +} diff --git a/i/simulotron/src/socket/socket_client.cc b/i/simulotron/src/socket/socket_client.cc index 6e18c2e..9dd19fa 100644 --- a/i/simulotron/src/socket/socket_client.cc +++ b/i/simulotron/src/socket/socket_client.cc @@ -35,14 +35,14 @@ SocketClient::SocketClient (void) // Crée le file descriptor du socket socket_ = socket (PF_INET, SOCK_STREAM, 0); if (socket_ < 0) - throw errno_exception ("La chaussette n'a pas pu être tricoté", errno); + throw errno_exception ("Socket: La chaussette n'a pas pu être tricoté", errno); } SocketClient::SocketClient (SocketServer & socketServer) { socket_ = socketServer.accept (); if (socket_ < 0) - throw errno_exception ("Problème lors de la construction d'une chaussette cliente par accept", errno); + throw errno_exception ("Socket: Problème lors de la construction d'une chaussette cliente par accept", errno); } SocketClient::~SocketClient (void) @@ -55,7 +55,7 @@ void SocketClient::connect (const Address & address) { if (::connect (socket_, address.getSockaddr (), sizeof (sockaddr_in)) < 0) - throw errno_exception ("Impossible de mettre la chaussette", errno); + throw errno_exception ("Socket: Impossible de mettre la chaussette", errno); } void @@ -64,12 +64,22 @@ SocketClient::connect (const std::string & address, int port) connect (Address(address, port)); } -std::string -SocketClient::read (void) +bool +SocketClient::read (std::string & strReaded, bool bloquant) { - std::string str; int charReaded; char buffer[BUFFER_SIZE]; + // Vérifie si il y a quelque chose à lire et retourne si non + if (!bloquant) + { + fd_set fds; + timeval tv = {0, 0}; + FD_ZERO(&fds); + FD_SET(socket_, &fds); + if(select(socket_ + 1, &fds, NULL, NULL, &tv) == 0) + return false; + } + strReaded.clear(); do { charReaded = ::read (socket_, buffer, BUFFER_SIZE - 1); @@ -77,9 +87,9 @@ SocketClient::read (void) throw errno_exception ("SocketClient: problème de lecture", errno); //buffer[charReaded] = 0; //str += buffer; - str.append(buffer, charReaded); + strReaded.append(buffer, charReaded); }while (charReaded == BUFFER_SIZE - 1); - return str; + return true; } void @@ -100,24 +110,8 @@ SocketClient::write (const std::string & str) } } -char -SocketClient::getChar (void) -{ - char getted; - if (::read (socket_, &getted, 1) < 0) - throw errno_exception ("SocketClient: erreur d'écriture (write()) ", errno); - return getted; -} - -void -SocketClient::putChar (char c) -{ - if (::write (socket_, &c, 1) < 0) - throw errno_exception ("SocketClient: erreur d'écriture (write()) ", errno); -} - -int -SocketClient::getFD(void) -{ - return socket_; -} +//int +//SocketClient::getFD(void) +//{ +// return socket_; +//} diff --git a/i/simulotron/src/socket/socket_client.hh b/i/simulotron/src/socket/socket_client.hh index 68bdd15..56d7afa 100644 --- a/i/simulotron/src/socket/socket_client.hh +++ b/i/simulotron/src/socket/socket_client.hh @@ -24,12 +24,15 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * }}} */ + +#include "utils/non_copyable.hh" + #include class Address; class SocketServer; -class SocketClient +class SocketClient :public NonCopyable { private: /// Ze socket @@ -49,15 +52,15 @@ class SocketClient /// Connect le client au serveur en se chargeant de créer Address void connect (const std::string & address, int port); /// lit du socket - std::string read (void); + bool read (std::string & strReaded, bool bloquant); /// écrit dans le socket void write (const std::string & str); /// lit un charactère du socket - char getChar (void); + //char getChar (bool bloquant); /// écrit un charactère dans le socket - void putChar (char c); + //void putChar (char c); /// Récupère le FD du socket - int getFD (void); + //int getFD (void); }; #endif //socket_client_hh diff --git a/i/simulotron/src/socket/socket_server.cc b/i/simulotron/src/socket/socket_server.cc index b5a511e..6cb8798 100644 --- a/i/simulotron/src/socket/socket_server.cc +++ b/i/simulotron/src/socket/socket_server.cc @@ -53,7 +53,7 @@ SocketServer::~SocketServer (void) SocketServer::listen (int maxQueue) { if (::listen (socket_, maxQueue) < 0 ) - throw errno_exception ("Impossible d'écouter la mer dans la chaussette", errno); + throw errno_exception ("Socket: Impossible d'écouter la mer dans la chaussette", errno); } int @@ -61,7 +61,7 @@ SocketServer::accept (void) { int socket = ::accept (socket_, 0, 0); if (socket < 0) - throw errno_exception ("Chaussette bloqué à la douane", errno); + throw errno_exception ("Socket: Chaussette bloqué à la douane", errno); return socket; } @@ -79,12 +79,12 @@ SocketServer::initSocket(const Address & address) // Crée le file descriptor du socket socket_ = socket (PF_INET, SOCK_STREAM, 0); if (socket_ < 0) - throw errno_exception ("La chaussette n'a pas pu être tricoté", errno); + throw errno_exception ("Socket: La chaussette n'a pas pu être tricoté", errno); // On règle la réusabilité du socket if (setsockopt (socket_, SOL_SOCKET, SO_REUSEADDR, &reuse_s, sizeof (int)) == -1) - throw errno_exception ("Erreur setsockopt : reusable", errno); + throw errno_exception ("Socket: Erreur setsockopt : reusable", errno); // On bind le socket if (::bind (socket_, address.getSockaddr (), sizeof (*address.getSockaddr ())) < 0) - throw errno_exception ("Impossible d'assigner la chausette", errno); + throw errno_exception ("Socket: Impossible d'assigner la chausette", errno); } diff --git a/i/simulotron/src/socket/socket_server.hh b/i/simulotron/src/socket/socket_server.hh index 67800f1..f2a022e 100644 --- a/i/simulotron/src/socket/socket_server.hh +++ b/i/simulotron/src/socket/socket_server.hh @@ -24,10 +24,13 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * }}} */ + +#include "utils/non_copyable.hh" + #include class Address; -class SocketServer +class SocketServer : public NonCopyable { private: /// Ze socket diff --git a/i/simulotron/src/socket/test_socket.cc b/i/simulotron/src/socket/test_socket.cc index 0724e8e..300dc13 100644 --- a/i/simulotron/src/socket/test_socket.cc +++ b/i/simulotron/src/socket/test_socket.cc @@ -80,7 +80,7 @@ int testSockServ(SocketServer & sockServ) // Acceptation d'une connection SocketClient sockFork(sockServ); // Reception d'un message - strDest = sockFork.read(); + sockFork.read(strDest, true); if(strDepart != strDest) { std::cout << "CHIER!! Le message d'origine est altéré en ecrivant du client au serveur!!" << std::endl; @@ -91,16 +91,16 @@ int testSockServ(SocketServer & sockServ) // Ecriture du serveur au client sockFork.write(strDepart); // Reception d'un char - b = sockFork.getChar(); - if(a != b) - { - std::cout << "CHIER!! Le char d'origine est altéré en ecrivant du client au serveur!!" << std::endl; - std::cout << "Le char d'origine: " << a << std::endl; - std::cout << "Le char d'arrivé: " << b << std::endl; - return 1; - } + //b = sockFork.getChar(); + //if(a != b) + //{ + // std::cout << "CHIER!! Le char d'origine est altéré en ecrivant du client au serveur!!" << std::endl; + // std::cout << "Le char d'origine: " << a << std::endl; + // std::cout << "Le char d'arrivé: " << b << std::endl; + // return 1; + //} // Ecriture du serveur vers le client - sockFork.putChar(a); + //sockFork.putChar(a); } catch(errno_exception & chier) { @@ -125,7 +125,7 @@ int testSockClient(int pauseMode) // Ecriture du client dans le serveur sockClient.write(strDepart); // Reception du message serveur - strDest = sockClient.read(); + sockClient.read(strDest, true); if(strDepart != strDest) { std::cout << "CHIER!! Le message d'origine est altéré en ecrivant du serveur au client!!" << std::endl; @@ -134,16 +134,16 @@ int testSockClient(int pauseMode) exit (1); } // Ecriture d'un char du client au serveur - sockClient.putChar(a); + //sockClient.putChar(a); // Reception d'un char - b = sockClient.getChar(); - if(a != b) - { - std::cout << "CHIER!! Le char d'origine est altéré en ecrivant du serveur au client!!" << std::endl; - std::cout << "Le char d'origine: " << a << std::endl; - std::cout << "Le char d'arrivé: " << b << std::endl; - exit (1); - } + //b = sockClient.getChar(); + //if(a != b) + //{ + // std::cout << "CHIER!! Le char d'origine est altéré en ecrivant du serveur au client!!" << std::endl; + // std::cout << "Le char d'origine: " << a << std::endl; + // std::cout << "Le char d'arrivé: " << b << std::endl; + // exit (1); + //} } catch(errno_exception & chier) { diff --git a/i/simulotron/src/utils/non_copyable.hh b/i/simulotron/src/utils/non_copyable.hh new file mode 100644 index 0000000..e788365 --- /dev/null +++ b/i/simulotron/src/utils/non_copyable.hh @@ -0,0 +1,41 @@ +#ifndef non_copyable_hh +#define non_copyable_hh +// non_copyable.hh +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} + +/// Toute classe qui hérite de NonCopyable ne peut pas être copiée. Cela est +/// assuré par le fait que l'operator= et le constructeur de recopie sont +/// privé. +/// Idée originale : Boost.org. +class NonCopyable +{ + public: + NonCopyable (void) { } + private: + NonCopyable (const NonCopyable &); + const NonCopyable &operator= (const NonCopyable &); +}; + +#endif // non_copyable_hh diff --git a/i/simulotron/src/utils/simulotron_exception.hh b/i/simulotron/src/utils/simulotron_exception.hh new file mode 100644 index 0000000..aeece4f --- /dev/null +++ b/i/simulotron/src/utils/simulotron_exception.hh @@ -0,0 +1,44 @@ +#ifndef simulotron_exception_hh +#define simulotron_exception_hh +// simulotron_exception.hh - exeption générale du simulotron +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2006 Nicolas Haller +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} + +#include +#include +#include +#include + +/// Exception lancé lorsqu'une erreur est retournée par la libc. +class simulotron_exception : public std::exception +{ + std::string what_; + public: + simulotron_exception (const std::string & module, const std::string & desc) + : what_ (module + ": " + desc) { } + ~simulotron_exception (void) throw () { } + virtual const char* what () const throw () { return what_.c_str (); } +}; + +#endif // simulotron_exception_hh -- cgit v1.2.3