summaryrefslogtreecommitdiff
path: root/cesar/maximus/coreengine/src/Maximus.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cesar/maximus/coreengine/src/Maximus.cpp')
-rw-r--r--cesar/maximus/coreengine/src/Maximus.cpp1289
1 files changed, 1289 insertions, 0 deletions
diff --git a/cesar/maximus/coreengine/src/Maximus.cpp b/cesar/maximus/coreengine/src/Maximus.cpp
new file mode 100644
index 0000000000..1686f3c811
--- /dev/null
+++ b/cesar/maximus/coreengine/src/Maximus.cpp
@@ -0,0 +1,1289 @@
+/************************************************************************
+ Maximus.cpp - Copyright buret
+
+Here you can write a license for your code, some comments or any other
+information you want to have in your generated code. To to this simply
+configure the "headings" directory in uml to point to a directory
+where you have your heading files.
+
+or you can just replace the contents of this file with your own.
+If you want to do this, this file is located at
+
+/usr/share/apps/umbrello/headings/heading.cpp
+
+-->Code Generators searches for heading files based on the file extension
+ i.e. it will look for a file name ending in ".h" to include in C++ header
+ files, and for a file name ending in ".java" to include in all generated
+ java code.
+ If you name the file "heading.<extension>", Code Generator will always
+ choose this file even if there are other files with the same extension in the
+ directory. If you name the file something else, it must be the only one with that
+ extension in the directory to guarantee that Code Generator will choose it.
+
+you can use variables in your heading files which are replaced at generation
+time. possible variables are : author, date, time, filename and filepath.
+just write %variable_name%
+
+This file was generated on %date% at %time%
+The original location of this file is /home/buret/eclipse/maximus/coreengine/src/Maximus.cpp
+**************************************************************************/
+
+#include "Maximus.h"
+
+#include "Sta.h"
+#include "Msg.h"
+#include "CoreEngine.h"
+#include "ISystem.h"
+#include "IFunctionCall.h"
+#include "INetworkClock.h"
+#include "ISci.h"
+#include "IChannel.h"
+#include "PhySciMsgMpdu.h"
+#include "ChannelSettings.h"
+
+#include "Error.h"
+#include "Logger.h"
+
+#include <stdio.h> // for 'remove()'
+#include <iostream> // for 'cout', 'cerr' and 'clog'
+#include <fstream> // for 'ifstream'
+#include <getopt.h> // for 'getopt_long()'
+#include <signal.h> // for 'signal()', 'SIGINT', 'raise()', 'SIGTERM'
+#include <algorithm> // for 'min()'
+using namespace std;
+
+// For unitary tests
+bool UNITTEST = false;
+string stationTest;
+
+// For Maximus log
+Logger logger(LOG_WARNING);
+
+// To catch signals
+Maximus * pMaximus;
+
+
+// Constructors/Destructors
+//
+
+
+Maximus::Maximus ( ):
+mpCoreEngine(NULL),
+mMaxTickValue(0),
+mWaitTickValue(0),
+mIsWireshark(false),
+mEtherLogFileDescriptor(-1)
+{
+ logFunction();
+
+ try
+ {
+ if (UNITTEST)
+ {
+ // For unitary tests log
+ logger.setLogLevel(LOG_DEBUG);
+ }
+
+ mpCoreEngine = new CoreEngine();
+ }
+ catchFunction(this);
+}
+
+
+Maximus::Maximus ( CoreEngine * p_core_engine ):
+mpCoreEngine(NULL),
+mMaxTickValue(0),
+mWaitTickValue(0)
+{
+ logFunction();
+
+ try
+ {
+ if (UNITTEST)
+ {
+ // For unitary tests log
+ logger.setLogLevel(LOG_DEBUG);
+
+ mpCoreEngine = p_core_engine;
+ }
+ else
+ {
+ errno = EBADRQC;
+ throw Error(__PRETTY_FUNCTION__, "FOR UNITARY TESTS ONLY", errno);
+ }
+ }
+ catchFunction(this);
+}
+
+
+Maximus::~Maximus ( )
+{
+ logFunction();
+
+ stop();
+}
+
+
+//
+// Methods
+//
+
+
+// public methods
+
+
+void Maximus::init ( int argc, char * argv[] )
+{
+ logFunction();
+
+ try
+ {
+ // To catch signals
+ pMaximus = this;
+ signal(SIGINT, Maximus::wrapper);
+
+ struct option longOptions[] = {
+ {"station-executable", required_argument, 0, 'e'},
+ {"station-log", required_argument, 0, 's'},
+ {"maximus-log", required_argument, 0, 'm'},
+ {"log-level", required_argument, 0, 'l'},
+ {"max-tick-value", required_argument, 0, 't'},
+ {"debugger", required_argument, 0, 'd'},
+ {"frequency", required_argument, 0, 'f'},
+ {"wireshark", required_argument, 0, 'w'}
+ };
+ int optionIndex = 0;
+ int optionChar = 0;
+
+ // Station executable
+ string stationExecutable;
+ bool isStationExecutableSet = false;
+
+ // Station log
+ string stationLog("-");
+
+ // Maximus log
+ string maximusLog("maximus_log");
+
+ // Log level
+ int logLevel = LOG_WARNING;
+
+ // Debugger
+ string debugger("xterm -title '\"%n\" debug' -e gdb %e %p & sleep 1");
+
+ // Frequency
+ float frequency = 50; // in Hz
+
+ // Wireshark
+ string wireshark;
+
+ while (EOF != optionChar)
+ {
+ optionChar = getopt_long(argc, argv, "e:s:m:l:t:d:f:w:", longOptions, &optionIndex);
+
+ switch (optionChar)
+ {
+ case 'e':
+ clog << logger(LOG_INFO) << "station executable = " << optarg << endl;
+ stationExecutable = optarg;
+ isStationExecutableSet = true;
+ break;
+ case 's':
+ clog << logger(LOG_INFO) << "station log = " << optarg << endl;
+ stationLog = optarg;
+ break;
+ case 'm':
+ clog << logger(LOG_INFO) << "maximus log = " << optarg << endl;
+ maximusLog = optarg;
+ break;
+ case 'l':
+ clog << logger(LOG_INFO) << "log level = " << optarg << endl;
+ if ((LOG_DEBUG <= atoi(optarg)) && (LOG_NONE >= atoi(optarg)))
+ {
+ logLevel = atoi(optarg);
+ }
+ else
+ {
+ clog << logger(LOG_ERROR) << "usage: -l log_level with log_level in range from 0 to 6!" << endl;
+ clog << logger(LOG_ERROR) << "user value is not taken into account => apply default value!" << endl;
+ }
+ break;
+ case 't':
+ clog << logger(LOG_INFO) << "max tick value = " << optarg << endl;
+ setMaxTickValue(atoi(optarg));
+ break;
+ case 'd':
+ clog << logger(LOG_INFO) << "debugger = " << optarg << endl;
+ debugger = optarg;
+ break;
+ case 'f':
+ clog << logger(LOG_INFO) << "frequency = " << optarg << endl;
+ if ((50 == atof(optarg)) || (60 == atof(optarg)) || (0 == atof(optarg)))
+ {
+ frequency = atof(optarg);
+ }
+ else
+ {
+ clog << logger(LOG_ERROR) << "usage: -f frequency with frequency 50 or 60 Hz, or 0!" << endl;
+ clog << logger(LOG_ERROR) << "user value is not taken into account => apply default value (50 Hz)!" << endl;
+ }
+ break;
+ case 'w':
+ clog << logger(LOG_INFO) << "wireshark = " << optarg << endl;
+ wireshark = optarg;
+ if ( (0 == wireshark.compare("on"))
+ || (0 == wireshark.compare("On"))
+ || (0 == wireshark.compare("ON")) )
+ {
+ mIsWireshark = true;
+ }
+ else if ( (0 == wireshark.compare("off"))
+ || (0 == wireshark.compare("Off"))
+ || (0 == wireshark.compare("OFF")) )
+ {
+ mIsWireshark = false;
+ }
+ else
+ {
+ clog << logger(LOG_ERROR) << "usage: -w wireshark with wireshark on or off!" << endl;
+ clog << logger(LOG_ERROR) << "user value is not taken into account => apply default value (off)!" << endl;
+ }
+ break;
+ case '?':
+ errno = EINVAL;
+ throw Error(__PRETTY_FUNCTION__, "Usage: -e station_executable [-s station_log -m maximus_log -l log_level -t max_tick_value -d debugger -f frequency -w wireshark]", errno);
+ break;
+ }
+ }
+
+ if (!isStationExecutableSet)
+ {
+ errno = EINVAL;
+ throw Error(__PRETTY_FUNCTION__, "Usage: -e station_executable [-s station_log -m maximus_log -l log_level -t max_tick_value -d debugger -f frequency -w wireshark]", errno);
+ }
+
+ // Maximus log
+ if ( (!maximusLog.empty()) && (maximusLog.compare("-")) )
+ {
+ // In case of the file already exists, delete it
+ remove(maximusLog.c_str());
+
+ mMaximusLogFile.open(maximusLog.c_str(), ios_base::app | ios_base::out);
+ if (mMaximusLogFile.is_open())
+ {
+ clog << logger(LOG_INFO) << "Maximus logs will be output into " << maximusLog << endl;
+ logger.setLogFile(mMaximusLogFile);
+ }
+ else
+ {
+ clog << logger(LOG_ERROR) << "error while opening Maximus log file!" << endl;
+ clog << logger(LOG_ERROR) << "Maximus logs will be output on standard output!" << endl;
+ }
+ }
+ else
+ {
+ clog << logger(LOG_ERROR) << "Maximus logs will be output on standard output!" << endl;
+ }
+
+ // Log level
+ logger.setLogLevel(logLevel);
+
+ mpCoreEngine->init(stationExecutable, stationLog, debugger, frequency);
+ }
+ catchFunction(this);
+}
+
+
+void Maximus::init_phy ( PhyMpduCb interface_cb )
+{
+ logFunction();
+
+ try
+ {
+ if (!getPhyProcessor()->init(interface_cb))
+ {
+ throw Error(__PRETTY_FUNCTION__, "PHY initialization failed");
+ }
+ }
+ catchFunction(this);
+}
+
+
+File_Descriptor Maximus::init_ether ( EtherCb interface_cb )
+{
+ logFunction();
+
+ try
+ {
+ if (!getEthernet()->init(interface_cb))
+ {
+ throw Error(__PRETTY_FUNCTION__, "Ethernet initialization failed");
+ }
+ if (isWireshark())
+ {
+ char dev[] = "tap10\0";
+ if (0 > (mEtherLogFileDescriptor = getEthernet()->allocTap(dev)))
+ {
+ throw Error(__PRETTY_FUNCTION__, "Bad Ether log file descriptor", errno);
+ }
+ }
+ }
+ catchFunction(this);
+
+ return mEtherLogFileDescriptor;
+}
+
+
+void Maximus::process ( )
+{
+ logFunction();
+
+ try
+ {
+ Network_Clock_Tick tickValue = 0; // tick value until which to process
+
+ if (0 == getMaxTickValue())
+ {
+ tickValue = getWaitTickValue();
+ }
+ else if (0 != getWaitTickValue())
+ {
+ tickValue = min(getMaxTickValue(), getWaitTickValue());
+ }
+
+ getCoreEngine()->process(tickValue);
+
+ if (0 != getMaxTickValue())
+ {
+ if (getMaxTickValue() <= getNetworkClockProcessor()->getCurrentTickValue())
+ {
+ clog << logger(LOG_FATAL) << "Max tick value is reached!" << endl;
+ stop();
+ exit(1);
+ }
+ }
+ }
+ catchFunction(this);
+}
+
+
+Sta & Maximus::create_sta ( const string & station_executable )
+{
+ logFunction();
+ Sta * pSta = NULL;
+
+ try
+ {
+ if (!station_executable.empty())
+ {
+ pSta = new Sta(this, getSystemManager(), station_executable);
+ }
+ else
+ {
+ pSta = new Sta(this, getSystemManager(), getSystemManager()->getDefaultStationExecutable());
+ }
+ if (NULL == pSta)
+ {
+ throw Error(__PRETTY_FUNCTION__, "Station pointer is NULL");
+ }
+ mListOfStas.push_back(pSta);
+
+ // If channel perturbation is enabled,
+ // inform the channel package that a new station has been created
+ if (getPhyProcessor()->isChannelEnabled())
+ {
+ getChannel()->addChannelSettings(pSta->getStationId());
+ }
+ }
+ catchFunction(this);
+
+ return *pSta;
+}
+
+
+Msg & Maximus::create_fc ( const string & name )
+{
+ logFunction();
+ Msg * pMsg = NULL;
+
+ try
+ {
+ pMsg = new Msg(this, getFunctionCallManager(), getSystemManager(), name);
+ if (NULL == pMsg)
+ {
+ throw Error(__PRETTY_FUNCTION__, "Message pointer is NULL");
+ }
+ mListOfMsgs.push_back(pMsg);
+ }
+ catchFunction(this);
+
+ return *pMsg;
+}
+
+
+Msg & Maximus::create_probe ( )
+{
+ logFunction();
+ Msg * pMsg = NULL;
+
+ try
+ {
+ pMsg = new Msg(this, getFunctionCallManager(), getSystemManager());
+ if (NULL == pMsg)
+ {
+ throw Error(__PRETTY_FUNCTION__, "Message pointer is NULL");
+ }
+ mListOfMsgs.push_back(pMsg);
+ }
+ catchFunction(this);
+
+ return *pMsg;
+}
+
+
+PhySciMsgMpdu * Maximus::create_mpdu ( )
+{
+ logFunction();
+
+ return getPhyProcessor()->createMpdu();
+}
+
+
+void Maximus::send_mpdu ( PhySciMsgMpdu * p_mpdu )
+{
+ logFunction();
+
+ try
+ {
+ if (NULL == p_mpdu)
+ {
+ errno = EINVAL;
+ throw Error(__PRETTY_FUNCTION__, "PHY SCI message MPDU pointer is NULL", errno);
+ }
+ if (!getPhyProcessor()->sendMpdu(p_mpdu))
+ {
+ throw Error(__PRETTY_FUNCTION__, "MPDU has not been sent correctly", errno);
+ }
+ }
+ catchFunction(this);
+}
+
+
+EtherSciMsg * Maximus::create_ether ( )
+{
+ logFunction();
+
+ return getEthernet()->createEther();
+}
+
+
+void Maximus::send_ether ( EtherSciMsg & ether )
+{
+ logFunction();
+
+ try
+ {
+ if (!getEthernet()->sendEther(ether))
+ {
+ throw Error(__PRETTY_FUNCTION__, "Ethernet SCI message has not been sent correctly", errno);
+ }
+ }
+ catchFunction(this);
+}
+
+
+void Maximus::wait ( const tick_t value )
+{
+ logFunction();
+
+ try
+ {
+ setWaitTickValue(getNetworkClockProcessor()->getCurrentTickValue() + value);
+ while (getWaitTickValue() > getNetworkClockProcessor()->getCurrentTickValue())
+ {
+ process();
+ }
+ setWaitTickValue(0);
+ }
+ catchFunction(this);
+}
+
+
+void Maximus::wait ( )
+{
+ logFunction();
+
+ try
+ {
+ while ( (NULL != getFunctionCallManager()->getListOfCallbacks())
+ && (!getFunctionCallManager()->getListOfCallbacks()->empty()) )
+ {
+ process();
+ }
+ }
+ catchFunction(this);
+}
+
+
+void Maximus::disturb_channel ( const bool enable )
+{
+ logFunction();
+
+ try
+ {
+ getCoreEngine()->disturbChannel(enable);
+ }
+ catchFunction(this);
+}
+
+
+const tick_t Maximus::get_date ( )
+{
+ logFunction();
+ tick_t date = 0;
+
+ try
+ {
+ date = getNetworkClockProcessor()->getCurrentTickValue();
+ }
+ catchFunction(this);
+
+ return date;
+}
+
+
+void Maximus::set_freq ( const float frequency )
+{
+ logFunction();
+
+ try
+ {
+ getPhyProcessor()->setFrequency(frequency);
+ }
+ catchFunction(this);
+}
+
+
+const float Maximus::get_freq ( )
+{
+ logFunction();
+ float frequency = 0;
+
+ try
+ {
+ frequency = getPhyProcessor()->getFrequency();
+ }
+ catchFunction(this);
+
+ return frequency;
+}
+
+
+void Maximus::set_snr ( const float snr_value )
+{
+ logFunction();
+
+ try
+ {
+ // If channel perturbation is enabled, set the SNR value
+ if (getPhyProcessor()->isChannelEnabled())
+ {
+ std::vector<ChannelSettings *> listOfChannelSettings = getChannel()->findChannelSettings(0 /* tx_station_id */, 0 /* rx_station_id */, false);
+ std::vector<ChannelSettings *>::size_type size = listOfChannelSettings.size();
+ for (std::vector<ChannelSettings *>::size_type s=0; s<size; s++)
+ {
+ if (NULL == listOfChannelSettings.back())
+ {
+ throw Error(__PRETTY_FUNCTION__, "A channel settings pointer is NULL");
+ }
+ else
+ {
+ listOfChannelSettings.back()->setSnr(snr_value);
+ }
+ listOfChannelSettings.pop_back();
+ }
+ }
+ else
+ {
+ errno = EPROTO;
+ throw Error(__PRETTY_FUNCTION__, "Channel perturbation is disabled", errno);
+ }
+ }
+ catchFunction(this);
+}
+
+
+void Maximus::set_snr ( const string & snr_file )
+{
+ logFunction();
+
+ try
+ {
+ // Read the user SNR file
+ float snrArray[MAXIMUS_CHANNEL_INTERVAL_MAX_NB][PHY_CARRIER_NB + 1];
+ if (!readSnrFile(snr_file, snrArray))
+ {
+ for (int j=0; j<= PHY_CARRIER_NB; j++)
+ {
+ for (int i=0; i<MAXIMUS_CHANNEL_INTERVAL_MAX_NB; i++)
+ {
+ cerr << snrArray[i][j] << " ";
+ }
+ cerr << endl;
+ }
+ errno = EINVAL;
+ throw Error(__PRETTY_FUNCTION__, "Error while reading SNR file", errno);
+ }
+
+ // If channel perturbation is enabled, set the SNR values
+ if (getPhyProcessor()->isChannelEnabled())
+ {
+ std::vector<ChannelSettings *> listOfChannelSettings = getChannel()->findChannelSettings(0 /* tx_station_id */, 0 /* rx_station_id */, false);
+ std::vector<ChannelSettings *>::size_type size = listOfChannelSettings.size();
+ for (std::vector<ChannelSettings *>::size_type s=0; s<size; s++)
+ {
+ if (NULL == listOfChannelSettings.back())
+ {
+ throw Error(__PRETTY_FUNCTION__, "A channel settings pointer is NULL");
+ }
+ else
+ {
+ listOfChannelSettings.back()->setSnr(snrArray);
+ }
+ listOfChannelSettings.pop_back();
+ }
+ }
+ else
+ {
+ errno = EPROTO;
+ throw Error(__PRETTY_FUNCTION__, "Channel perturbation is disabled", errno);
+ }
+ }
+ catchFunction(this);
+}
+
+
+void Maximus::set_snr_from_src ( const float snr_value, const Sta & src, const bool both_directions )
+{
+ logFunction();
+
+ try
+ {
+ // If channel perturbation is enabled, set the SNR value
+ if (getPhyProcessor()->isChannelEnabled())
+ {
+ std::vector<ChannelSettings *> listOfChannelSettings = getChannel()->findChannelSettings(src.getStationId() /* tx_station_id */, 0 /* rx_station_id */, both_directions);
+ std::vector<ChannelSettings *>::size_type size = listOfChannelSettings.size();
+ for (std::vector<ChannelSettings *>::size_type s=0; s<size; s++)
+ {
+ if (NULL == listOfChannelSettings.back())
+ {
+ throw Error(__PRETTY_FUNCTION__, "A channel settings pointer is NULL");
+ }
+ else
+ {
+ listOfChannelSettings.back()->setSnr(snr_value);
+ }
+ listOfChannelSettings.pop_back();
+ }
+ }
+ else
+ {
+ errno = EPROTO;
+ throw Error(__PRETTY_FUNCTION__, "Channel perturbation is disabled", errno);
+ }
+ }
+ catchFunction(this);
+}
+
+
+void Maximus::set_snr_from_src ( const string & snr_file, const Sta & src, const bool both_directions )
+{
+ logFunction();
+
+ try
+ {
+ // Read the user SNR file
+ float snrArray[MAXIMUS_CHANNEL_INTERVAL_MAX_NB][PHY_CARRIER_NB + 1];
+ if (!readSnrFile(snr_file, snrArray))
+ {
+ for (int j=0; j<= PHY_CARRIER_NB; j++)
+ {
+ for (int i=0; i<MAXIMUS_CHANNEL_INTERVAL_MAX_NB; i++)
+ {
+ cerr << snrArray[i][j] << " ";
+ }
+ cerr << endl;
+ }
+ errno = EINVAL;
+ throw Error(__PRETTY_FUNCTION__, "Error while reading SNR file", errno);
+ }
+
+ // If channel perturbation is enabled, set the SNR values
+ if (getPhyProcessor()->isChannelEnabled())
+ {
+ std::vector<ChannelSettings *> listOfChannelSettings = getChannel()->findChannelSettings(src.getStationId() /* tx_station_id */, 0 /* rx_station_id */, both_directions);
+ std::vector<ChannelSettings *>::size_type size = listOfChannelSettings.size();
+ for (std::vector<ChannelSettings *>::size_type s=0; s<size; s++)
+ {
+ if (NULL == listOfChannelSettings.back())
+ {
+ throw Error(__PRETTY_FUNCTION__, "A channel settings pointer is NULL");
+ }
+ else
+ {
+ listOfChannelSettings.back()->setSnr(snrArray);
+ }
+ listOfChannelSettings.pop_back();
+ }
+ }
+ else
+ {
+ errno = EPROTO;
+ throw Error(__PRETTY_FUNCTION__, "Channel perturbation is disabled", errno);
+ }
+ }
+ catchFunction(this);
+}
+
+
+void Maximus::set_snr_to_dst ( const float snr_value, const Sta & dst, const bool both_directions )
+{
+ logFunction();
+
+ try
+ {
+ // If channel perturbation is enabled, set the SNR value
+ if (getPhyProcessor()->isChannelEnabled())
+ {
+ std::vector<ChannelSettings *> listOfChannelSettings = getChannel()->findChannelSettings(0 /* tx_station_id */, dst.getStationId() /* rx_station_id */, both_directions);
+ std::vector<ChannelSettings *>::size_type size = listOfChannelSettings.size();
+ for (std::vector<ChannelSettings *>::size_type s=0; s<size; s++)
+ {
+ if (NULL == listOfChannelSettings.back())
+ {
+ throw Error(__PRETTY_FUNCTION__, "A channel settings pointer is NULL");
+ }
+ else
+ {
+ listOfChannelSettings.back()->setSnr(snr_value);
+ }
+ listOfChannelSettings.pop_back();
+ }
+ }
+ else
+ {
+ errno = EPROTO;
+ throw Error(__PRETTY_FUNCTION__, "Channel perturbation is disabled", errno);
+ }
+ }
+ catchFunction(this);
+}
+
+
+void Maximus::set_snr_to_dst ( const string & snr_file, const Sta & dst, const bool both_directions )
+{
+ logFunction();
+
+ try
+ {
+ // Read the user SNR file
+ float snrArray[MAXIMUS_CHANNEL_INTERVAL_MAX_NB][PHY_CARRIER_NB + 1];
+ if (!readSnrFile(snr_file, snrArray))
+ {
+ for (int j=0; j<= PHY_CARRIER_NB; j++)
+ {
+ for (int i=0; i<MAXIMUS_CHANNEL_INTERVAL_MAX_NB; i++)
+ {
+ cerr << snrArray[i][j] << " ";
+ }
+ cerr << endl;
+ }
+ errno = EINVAL;
+ throw Error(__PRETTY_FUNCTION__, "Error while reading SNR file", errno);
+ }
+
+ // If channel perturbation is enabled, set the SNR values
+ if (getPhyProcessor()->isChannelEnabled())
+ {
+ std::vector<ChannelSettings *> listOfChannelSettings = getChannel()->findChannelSettings(0 /* tx_station_id */, dst.getStationId() /* rx_station_id */, both_directions);
+ std::vector<ChannelSettings *>::size_type size = listOfChannelSettings.size();
+ for (std::vector<ChannelSettings *>::size_type s=0; s<size; s++)
+ {
+ if (NULL == listOfChannelSettings.back())
+ {
+ throw Error(__PRETTY_FUNCTION__, "A channel settings pointer is NULL");
+ }
+ else
+ {
+ listOfChannelSettings.back()->setSnr(snrArray);
+ }
+ listOfChannelSettings.pop_back();
+ }
+ }
+ else
+ {
+ errno = EPROTO;
+ throw Error(__PRETTY_FUNCTION__, "Channel perturbation is disabled", errno);
+ }
+ }
+ catchFunction(this);
+}
+
+
+void Maximus::set_snr_from_src_to_dst ( const float snr_value, const Sta & src, const Sta & dst, const bool both_directions )
+{
+ logFunction();
+
+ try
+ {
+ // If channel perturbation is enabled, set the SNR value
+ if (getPhyProcessor()->isChannelEnabled())
+ {
+ std::vector<ChannelSettings *> listOfChannelSettings = getChannel()->findChannelSettings(src.getStationId() /* tx_station_id */, dst.getStationId() /* rx_station_id */, both_directions);
+ std::vector<ChannelSettings *>::size_type size = listOfChannelSettings.size();
+ for (std::vector<ChannelSettings *>::size_type s=0; s<size; s++)
+ {
+ if (NULL == listOfChannelSettings.back())
+ {
+ throw Error(__PRETTY_FUNCTION__, "A channel settings pointer is NULL");
+ }
+ else
+ {
+ listOfChannelSettings.back()->setSnr(snr_value);
+ }
+ listOfChannelSettings.pop_back();
+ }
+ }
+ else
+ {
+ errno = EPROTO;
+ throw Error(__PRETTY_FUNCTION__, "Channel perturbation is disabled", errno);
+ }
+ }
+ catchFunction(this);
+}
+
+
+void Maximus::set_snr_from_src_to_dst ( const string & snr_file, const Sta & src, const Sta & dst, const bool both_directions )
+{
+ logFunction();
+
+ try
+ {
+ float snrArray[MAXIMUS_CHANNEL_INTERVAL_MAX_NB][PHY_CARRIER_NB + 1];
+ if (!readSnrFile(snr_file, snrArray))
+ {
+ for (int j=0; j<= PHY_CARRIER_NB; j++)
+ {
+ for (int i=0; i<MAXIMUS_CHANNEL_INTERVAL_MAX_NB; i++)
+ {
+ cerr << snrArray[i][j] << " ";
+ }
+ cerr << endl;
+ }
+ errno = EINVAL;
+ throw Error(__PRETTY_FUNCTION__, "Error while reading SNR file", errno);
+ }
+
+ // If channel perturbation is enabled, set the SNR values
+ if (getPhyProcessor()->isChannelEnabled())
+ {
+ std::vector<ChannelSettings *> listOfChannelSettings = getChannel()->findChannelSettings(src.getStationId() /* tx_station_id */, dst.getStationId() /* rx_station_id */, both_directions);
+ std::vector<ChannelSettings *>::size_type size = listOfChannelSettings.size();
+ for (std::vector<ChannelSettings *>::size_type s=0; s<size; s++)
+ {
+ if (NULL == listOfChannelSettings.back())
+ {
+ throw Error(__PRETTY_FUNCTION__, "A channel settings pointer is NULL");
+ }
+ else
+ {
+ listOfChannelSettings.back()->setSnr(snrArray);
+ }
+ listOfChannelSettings.pop_back();
+ }
+ }
+ else
+ {
+ errno = EPROTO;
+ throw Error(__PRETTY_FUNCTION__, "Channel perturbation is disabled", errno);
+ }
+ }
+ catchFunction(this);
+}
+
+
+void Maximus::activate_false_alarm ( const Network_Clock_Tick average_duration,
+ const float std_deviation )
+{
+ logFunction();
+
+ try
+ {
+ if (!getPhyProcessor()->activateFalseAlarm(average_duration, std_deviation))
+ {
+ throw Error(__PRETTY_FUNCTION__, "Cannot activate false alarm");
+ }
+ }
+ catchFunction(this);
+}
+
+
+void Maximus::deactivate_false_alarm ( )
+{
+ logFunction();
+
+ try
+ {
+ if (!getPhyProcessor()->deactivateFalseAlarm())
+ {
+ throw Error(__PRETTY_FUNCTION__, "Cannot deactivate false alarm");
+ }
+ }
+ catchFunction(this);
+}
+
+
+const bool Maximus::is_station_idle ( Sci_Msg_Station_Id station_id )
+{
+ logFunction();
+ bool isIdle = false;
+
+ try
+ {
+ isIdle = getSystemManager()->isStationIdle(station_id);
+ }
+ catchFunction(this);
+
+ return isIdle;
+}
+
+
+// private methods
+//
+
+
+CoreEngine * Maximus::getCoreEngine ( )
+{
+ try
+ {
+ if (NULL == mpCoreEngine)
+ {
+ throw Error(__PRETTY_FUNCTION__, "Core engine pointer is NULL");
+ }
+ }
+ catchFunction(this);
+
+ return mpCoreEngine;
+}
+
+
+ISystem * Maximus::getSystemManager ( )
+{
+ ISystem * pSystemManager = NULL;
+
+ try
+ {
+ if ( NULL == (pSystemManager = getCoreEngine()->getSystem()) )
+ {
+ throw Error(__PRETTY_FUNCTION__, "System manager pointer is NULL");
+ }
+ }
+ catchFunction(this);
+
+ return pSystemManager;
+}
+
+
+IFunctionCall * Maximus::getFunctionCallManager ( )
+{
+ IFunctionCall * pFunctionCallManager = NULL;
+
+ try
+ {
+ if ( NULL == (pFunctionCallManager = getCoreEngine()->getFunctionCall()) )
+ {
+ throw Error(__PRETTY_FUNCTION__, "Function call manager pointer is NULL");
+ }
+ }
+ catchFunction(this);
+
+ return pFunctionCallManager;
+}
+
+
+INetworkClock * Maximus::getNetworkClockProcessor ( )
+{
+ INetworkClock * pNetworkClockProcessor = NULL;
+
+ try
+ {
+ if ( NULL == (pNetworkClockProcessor = getCoreEngine()->getNetworkClock()) )
+ {
+ throw Error(__PRETTY_FUNCTION__, "Network clock processor pointer is NULL");
+ }
+ }
+ catchFunction(this);
+
+ return pNetworkClockProcessor;
+}
+
+
+IPhy * Maximus::getPhyProcessor ( )
+{
+ IPhy * pPhyProcessor = NULL;
+
+ try
+ {
+ if ( NULL == (pPhyProcessor = getCoreEngine()->getPhy()) )
+ {
+ throw Error(__PRETTY_FUNCTION__, "Phy processor pointer is NULL");
+ }
+ }
+ catchFunction(this);
+
+ return pPhyProcessor;
+}
+
+
+ISci * Maximus::getSciServer ( )
+{
+ ISci * pSciServer = NULL;
+
+ try
+ {
+ if ( NULL == (pSciServer = getCoreEngine()->getSci()) )
+ {
+ throw Error(__PRETTY_FUNCTION__, "SCI server pointer is NULL");
+ }
+ }
+ catchFunction(this);
+
+ return pSciServer;
+}
+
+
+IChannel * Maximus::getChannel ( )
+{
+ IChannel * pChannel = NULL;
+
+ try
+ {
+ if ( NULL == (pChannel = getCoreEngine()->getChannel()) )
+ {
+ throw Error(__PRETTY_FUNCTION__, "Channel pointer is NULL");
+ }
+ }
+ catchFunction(this);
+
+ return pChannel;
+}
+
+
+IEthernet * Maximus::getEthernet ( )
+{
+ IEthernet * pEthernet = NULL;
+
+ try
+ {
+ if ( NULL == (pEthernet = getCoreEngine()->getEthernet()) )
+ {
+ throw Error(__PRETTY_FUNCTION__, "Ethernet pointer is NULL");
+ }
+ }
+ catchFunction(this);
+
+ return pEthernet;
+}
+
+
+Network_Clock_Tick Maximus::getMaxTickValue ( ) const
+{
+ return mMaxTickValue;
+}
+
+
+bool Maximus::setMaxTickValue ( const Network_Clock_Tick max_tick_value )
+{
+ mMaxTickValue = max_tick_value;
+
+ return true;
+}
+
+
+Network_Clock_Tick Maximus::getWaitTickValue ( ) const
+{
+ return mWaitTickValue;
+}
+
+
+bool Maximus::setWaitTickValue ( const Network_Clock_Tick wait_tick_value )
+{
+ mWaitTickValue = wait_tick_value;
+
+ return true;
+}
+
+
+bool Maximus::readSnrFile ( const string & snr_file, float snr_array[MAXIMUS_CHANNEL_INTERVAL_MAX_NB][PHY_CARRIER_NB + 1] )
+{
+ logFunction();
+ bool bRead = true;
+
+ try
+ {
+ // Read file
+ //
+ memset(snr_array, '\0', MAXIMUS_CHANNEL_INTERVAL_MAX_NB * (PHY_CARRIER_NB + 1) * sizeof(float));
+ ifstream snrFile(snr_file.c_str(), ifstream::in);
+ if (snrFile.is_open())
+ {
+ /* Read end times (in ticks) of each interval of the beacon period. */
+ char c;
+ float tempEndTimeOfLastInterval = (2 * 1000000) / (getPhyProcessor()->getFrequency());
+ unsigned short int endTimeOfLastInterval = (unsigned short int)tempEndTimeOfLastInterval;
+ unsigned short int numberOfIntervals = MAXIMUS_CHANNEL_INTERVAL_MAX_NB;
+ for (int i=0; i<MAXIMUS_CHANNEL_INTERVAL_MAX_NB; i++)
+ {
+ snrFile >> snr_array[i][0];
+ if (endTimeOfLastInterval <= snr_array[i][0])
+ {
+ snr_array[i][0] = endTimeOfLastInterval;
+ numberOfIntervals = i + 1;
+ break;
+ }
+ c = snrFile.peek();
+ while ( ('\t' == c) || (' ' == c) || (EOF == c) )
+ {
+ snrFile.ignore();
+ c = snrFile.peek();
+ }
+ if ('#' == c)
+ {
+ while ( ('\n' != c) && (EOF != c) )
+ {
+ snrFile.ignore();
+ c = snrFile.peek();
+ }
+ }
+ if ('\n' == c)
+ {
+ snrFile.ignore();
+ numberOfIntervals = i + 1;
+ if (endTimeOfLastInterval != snr_array[i][0])
+ {
+ if (MAXIMUS_CHANNEL_INTERVAL_MAX_NB > i+1)
+ {
+ snr_array[i+1][0] = endTimeOfLastInterval;
+ numberOfIntervals++;
+ }
+ else
+ {
+ errno = EINVAL;
+ throw Error(__PRETTY_FUNCTION__, "Too many time intervals in SNR file", errno);
+ }
+ }
+ break;
+ }
+ }
+
+ /* Read SNR values (in dB) for each carrier. */
+ for (int j=1; j<=PHY_CARRIER_NB; j++)
+ {
+ for (int i=0; i<numberOfIntervals; i++)
+ {
+ snrFile >> snr_array[i][j];
+ }
+ c = snrFile.peek();
+ while ( ('\n' != c) && (EOF != c) )
+ {
+ snrFile.ignore();
+ c = snrFile.peek();
+ }
+ }
+ }
+ else
+ {
+ throw Error(__PRETTY_FUNCTION__, "Error while opening SNR file", errno);
+ }
+ snrFile.close();
+ }
+ catchFunction(this);
+
+ return bRead;
+}
+
+
+const bool Maximus::isWireshark ( ) const
+{
+ return mIsWireshark;
+}
+
+
+// public methods
+//
+
+
+void Maximus::wrapper ( int n )
+{
+ logFunction();
+
+ if (NULL != pMaximus)
+ {
+ clog << logger(LOG_FATAL) << "Catch CTRL+C!" << endl;
+ pMaximus->stop();
+ raise(SIGTERM);
+ }
+}
+
+
+void Maximus::stop ( )
+{
+ logFunction();
+ unsigned int counter = 0;
+
+ clog << logger(LOG_FATAL) << "*** Exit Fulminata Maximus simulator ***" << endl;
+
+ for (unsigned int i=0; i<mListOfMsgs.size(); i++)
+ {
+ if (NULL != mListOfMsgs[i])
+ {
+ delete (mListOfMsgs[i]);
+ counter ++;
+ }
+ }
+ mListOfMsgs.clear();
+ clog << logger(LOG_FATAL) << "delete " << counter << " messages" << endl;
+ counter = 0;
+
+ for (unsigned int i=0; i<mListOfStas.size(); i++)
+ {
+ if (NULL != mListOfStas[i])
+ {
+ delete (mListOfStas[i]);
+ counter++;
+ }
+ }
+ mListOfStas.clear();
+ clog << logger(LOG_FATAL) << "delete " << counter << " stations" << endl;
+
+ if (mMaximusLogFile.is_open())
+ {
+ mMaximusLogFile.flush();
+ mMaximusLogFile.close();
+ }
+
+ if (0 <= mEtherLogFileDescriptor)
+ {
+ close(mEtherLogFileDescriptor);
+ }
+
+ // Warning: delete the Core Engine is the last task to do!
+ if (NULL != mpCoreEngine)
+ {
+ delete mpCoreEngine;
+ mpCoreEngine = NULL;
+ }
+}
+