Commit e85cb58e authored by garciay's avatar garciay
Browse files

Start testing DENM

parent 66c2d2f1
#include "LibItsDenm_EncdecDeclarations.hh"
#include "DENMCodec.hh"
#include "loggers.hh"
namespace LibItsDenm__EncdecDeclarations {
/****************************************************
* @desc External function to encode a DenmReq type
* @param value to encode
* @return encoded value
****************************************************/
BITSTRING fx__enc__DenmReq(const LibItsDenm__TestSystem::DenmReq& p)
{
//set error behavior
// TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL,TTCN_EncDec::EB_WARNING);
TTCN_Buffer TTCN_buf;
TTCN_buf.clear();
//encode message in BER (CER variant, but can be any)
// p.msgOut().encode(DENM__PDU__Descriptions::DENM_descr_,TTCN_buf,TTCN_EncDec::CT_BER,BER_ENCODE_CER);
OCTETSTRING encodedData(TTCN_buf.get_len(), TTCN_buf.get_data());
//insert BER2PER recoding here!
return oct2bit(encodedData);
}
/****************************************************
* @desc External function to decode a DenmReq type
* @param value to encode
* @return encoded value
****************************************************/
//function not needed yet, decvalue() is not used in TTCN-3 code
INTEGER fx__dec__DenmReq(BITSTRING& b, LibItsDenm__TestSystem::DenmReq& p)
{
return -1;
}
INTEGER fx__dec__DenmInd(BITSTRING& b, LibItsDenm__TestSystem::DenmInd& p)
{
return -1;
}
/****************************************************
* @desc External function to encode a DenmReq type
* @param value to encode
* @return encoded value
****************************************************/
BITSTRING fx__enc__DenmReq(const LibItsDenm__TestSystem::DenmReq& p_denmReq)
{
loggers::get_instance().log_msg(">>> fx__enc__DenmReq: ", p_denmReq);
DENMCodec codec;
OCTETSTRING os;
if (codec.encode(p_denmReq.msgOut(), os) == -1) {
loggers::get_instance().warning("fx__enc__DenmReq: -1 result code was returned");
return int2bit(0, 1);
}
return oct2bit(os);
}
/****************************************************
* @desc External function to decode a DenmReq type
* @param value to encode
* @return encoded value
****************************************************/
INTEGER fx__dec__DenmReq(BITSTRING& b, LibItsDenm__TestSystem::DenmReq& p)
{
loggers::get_instance().log(">>> fx__dec__DenmReq");
DENMCodec codec;
DENM__PDU__Descriptions::DENM denm;
OCTETSTRING is = bit2oct(b);
if (codec.decode(is, denm) == -1) {
loggers::get_instance().warning("fx__dec__DenmReq: -1 result code was returned");
return -1;
}
p.msgOut() = denm;
return 0;
}
INTEGER fx__dec__DenmInd(BITSTRING& b, LibItsDenm__TestSystem::DenmInd& p_denmInd)
{
loggers::get_instance().log_msg(">>> fx__enc__DenmInd: ", p_denmInd);
DENMCodec codec;
DENM__PDU__Descriptions::DENM denm;
OCTETSTRING is = bit2oct(b);
// Calculate the size of the lower layers information
int s = (LibItsGeoNetworking__TestSystem::GeoNetworkingInd_macDestinationAddress_raw_.fieldlength + LibItsGeoNetworking__TestSystem::GeoNetworkingInd_its__aid_raw_.fieldlength) / 8;
if (codec.decode(OCTETSTRING(is.lengthof() - s, static_cast<const unsigned char *>(is)), denm) == -1) {
loggers::get_instance().warning("fx__dec__DenmInd: -1 result code was returned");
return -1;
}
p_denmInd.msgIn() = denm;
TTCN_Buffer decoding_buffer(OCTETSTRING(is.lengthof() - s, static_cast<const unsigned char *>(is) + is.lengthof() - s));
for (int i = 1; i < p_denmInd.get_count(); i++) {
p_denmInd.get_at(i)->decode(*p_denmInd.fld_descr(i), decoding_buffer, TTCN_EncDec::CT_RAW);
} // End of 'for' statement
return 0;
}
BITSTRING fx__enc__DENM(const DENM__PDU__Descriptions::DENM& p_denm)
{
loggers::get_instance().log_msg(">>> fx__enc__DENM: ", p_denm);
DENMCodec codec;
OCTETSTRING os;
codec.encode(p_denm, os);
return oct2bit(os);
}
INTEGER fx__dec__DENM(BITSTRING& b, DENM__PDU__Descriptions::DENM& p)
{
loggers::get_instance().log(">>> fx__dec__DENM");
DENMCodec codec;
OCTETSTRING is = bit2oct(b);
if (codec.decode(OCTETSTRING(is.lengthof(), static_cast<const unsigned char *>(is)), p) == -1) {
loggers::get_instance().warning("fx__dec__DENM: -1 result code was returned");
return -1;
}
return 0;
}
} //end namespace
......@@ -8,70 +8,99 @@
// add your member functions here.
#include "DenmPort.hh"
#include "DENMLayer.hh"
#include "loggers.hh"
namespace LibItsDenm__TestSystem {
DenmPort::DenmPort(const char *par_port_name)
: DenmPort_BASE(par_port_name)
{
}
DenmPort::~DenmPort()
{
}
void DenmPort::set_parameter(const char * /*parameter_name*/,
const char * /*parameter_value*/)
{
}
/*void DenmPort::Handle_Fd_Event(int fd, boolean is_readable,
boolean is_writable, boolean is_error) {}*/
void DenmPort::Handle_Fd_Event_Error(int /*fd*/)
{
}
void DenmPort::Handle_Fd_Event_Writable(int /*fd*/)
{
}
void DenmPort::Handle_Fd_Event_Readable(int /*fd*/)
{
}
/*void DenmPort::Handle_Timeout(double time_since_last_call) {}*/
void DenmPort::user_map(const char * /*system_port*/)
{
}
void DenmPort::user_unmap(const char * /*system_port*/)
{
}
void DenmPort::user_start()
{
}
void DenmPort::user_stop()
{
}
void DenmPort::outgoing_send(const DenmReq& /*send_par*/)
{
}
DenmPort::DenmPort(const char *par_port_name) : DenmPort_BASE(par_port_name), _cfg_params(), _layer_params(), _layer(NULL), _time_key("DenmPort::outgoing_send") {
}
DenmPort::~DenmPort()
{
if (_layer != NULL) {
delete _layer;
}
}
void DenmPort::set_parameter(const char * parameter_name, const char * parameter_value)
{
loggers::get_instance().log("DenmPort::set_parameter: %s=%s", parameter_name, parameter_value);
_cfg_params.insert(std::pair<std::string, std::string>(std::string(parameter_name), std::string(parameter_value)));
}
/*void DenmPort::Handle_Fd_Event(int fd, boolean is_readable,
boolean is_writable, boolean is_error) {}*/
void DenmPort::Handle_Fd_Event_Error(int /*fd*/)
{
}
void DenmPort::Handle_Fd_Event_Writable(int /*fd*/)
{
}
void DenmPort::Handle_Fd_Event_Readable(int /*fd*/)
{
}
/*void DenmPort::Handle_Timeout(double time_since_last_call) {}*/
void DenmPort::user_map(const char * system_port)
{
loggers::get_instance().log(">>> DenmPort::user_map: %s", system_port);
// Build layer stack
std::map<std::string, std::string>::iterator it = _cfg_params.find(std::string("params"));
if (it != _cfg_params.end()) {
loggers::get_instance().log("DenmPort::user_map: %s", it->second.c_str());
_layer = LayerStackBuilder::GetInstance()->createLayerStack(it->second.c_str());
if (static_cast<DENMLayer *>(_layer) == NULL) {
loggers::get_instance().error("DenmPort::user_map: Invalid stack configuration: %s", it->second.c_str());
}
static_cast<DENMLayer *>(_layer)->addUpperPort(this);
} else {
loggers::get_instance().error("DenmPort::user_map: No layers defined in configuration file");
}
}
void DenmPort::user_unmap(const char * system_port)
{
loggers::get_instance().log(">>> DenmPort::user_unmap: %s", system_port);
if (_layer != NULL) {
delete _layer;
_layer = NULL;
}
}
void DenmPort::user_start()
{
}
void DenmPort::user_stop()
{
}
void DenmPort::outgoing_send(const DenmReq& send_par)
{
loggers::get_instance().log_msg(">>> DenmPort::outgoing_send: payload=", send_par);
float duration;
loggers::get_instance().set_start_time(_time_key);
static_cast<DENMLayer *>(_layer)->sendMsg(send_par, _layer_params);
loggers::get_instance().set_stop_time(_time_key, duration);
}
void DenmPort::receiveMsg(const LibItsDenm__TestSystem::DenmInd& p_ind, const Params& p_params) {
loggers::get_instance().log_msg(">>> DenmPort::receive_msg: ", p_ind);
incoming_message(p_ind);
}
} /* end of namespace */
......@@ -12,32 +12,41 @@
#include "LibItsDenm_TestSystem.hh"
#include "Layer.hh"
#include "Params.hh"
namespace LibItsDenm__TestSystem {
class DenmPort : public DenmPort_BASE {
public:
DenmPort(const char *par_port_name = NULL);
~DenmPort();
void set_parameter(const char *parameter_name,
const char *parameter_value);
private:
/* void Handle_Fd_Event(int fd, boolean is_readable,
boolean is_writable, boolean is_error); */
void Handle_Fd_Event_Error(int fd);
void Handle_Fd_Event_Writable(int fd);
void Handle_Fd_Event_Readable(int fd);
/* void Handle_Timeout(double time_since_last_call); */
protected:
void user_map(const char *system_port);
void user_unmap(const char *system_port);
void user_start();
void user_stop();
void outgoing_send(const DenmReq& send_par);
};
class DenmPort : public DenmPort_BASE {
Params _cfg_params;
Params _layer_params;
Layer * _layer;
std::string _time_key;
public:
DenmPort(const char *par_port_name = NULL);
~DenmPort();
void set_parameter(const char *parameter_name,
const char *parameter_value);
void receiveMsg (const LibItsDenm__TestSystem::DenmInd&, const Params&);
private:
/* void Handle_Fd_Event(int fd, boolean is_readable,
boolean is_writable, boolean is_error); */
void Handle_Fd_Event_Error(int fd);
void Handle_Fd_Event_Writable(int fd);
void Handle_Fd_Event_Readable(int fd);
/* void Handle_Timeout(double time_since_last_call); */
protected:
void user_map(const char *system_port);
void user_unmap(const char *system_port);
void user_start();
void user_stop();
void outgoing_send(const DenmReq& send_par);
};
} /* end of namespace */
......
......@@ -7,10 +7,6 @@
// You may modify this file. Complete the body of empty functions and
// add your member functions here.
/*#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>*/
#include "GeoNetworkingPort.hh"
#include "GeoNetworkingLayer.hh"
#include "loggers.hh"
......@@ -18,7 +14,7 @@
namespace LibItsGeoNetworking__TestSystem {
GeoNetworkingPort::GeoNetworkingPort(const char *par_port_name)
: GeoNetworkingPort_BASE(par_port_name), _cfg_params(), _layer_params(), _layer(NULL), _time_key("GeoNetworkingPort::outgoing_send") /*, _use_posix_timer(true), _child(-1), _child_pids{-1, -1}, _parent_pids{-1, -1}, _timerid{0}, _sev{0}, _its{0}, _freq_nanosecs(0), _mask{0}, _sa{0}*/ {
: GeoNetworkingPort_BASE(par_port_name), _cfg_params(), _layer_params(), _layer(NULL), _time_key("GeoNetworkingPort::outgoing_send") {
// Nothing to do
} // End of constructor
......@@ -26,9 +22,6 @@ namespace LibItsGeoNetworking__TestSystem {
{
loggers::get_instance().log(">>> GeoNetworkingPort::~GeoNetworkingPort");
/*if (_use_posix_timer && (_timerid != 0)) {
timer_delete(_timerid);
}*/
if (_layer != NULL) {
delete _layer;
}
......@@ -75,73 +68,6 @@ namespace LibItsGeoNetworking__TestSystem {
loggers::get_instance().error("GeoNetworkingPort::user_map: Invalid stack configuration: %s", it->second.c_str());
}
static_cast<GeoNetworkingLayer *>(_layer)->addUpperPort(this);
/*if (_use_posix_timer) {
// Establish handler for timer signal
loggers::get_instance().log("GeoNetworkingPort::user_map: Establishing handler for signal %d\n", SIGALRM);
_sa.sa_flags = SA_SIGINFO;
_sa.sa_sigaction = timer_irq_sigalrm_handler;
sigemptyset(&_sa.sa_mask);
if (sigaction(SIGALRM, &_sa, NULL) == -1) {
loggers::get_instance().error("GeoNetworkingPort::user_map: Sigaction failure: %d", errno);
}
// Block timer signal temporarily
loggers::get_instance().log("GeoNetworkingPort::user_map: Blocking signal %d\n", SIGALRM);
sigemptyset(&_mask);
sigaddset(&_mask, SIGALRM);
if (sigprocmask(SIG_SETMASK, &_mask, NULL) == -1) {
loggers::get_instance().error("GeoNetworkingPort::user_map: Sigprocmask failure: %d", errno);
}
// Create the timer
_sev.sigev_notify = SIGEV_SIGNAL;
_sev.sigev_signo = SIGALRM; // Use signal alarm
_sev.sigev_value.sival_ptr = this; // The GeoNetworkingPort object address
if (timer_create(CLOCK_REALTIME, &_sev, &_timerid) == -1) {
loggers::get_instance().error("GeoNetworkingPort::user_map: Timer failure: %d", errno);
}
loggers::get_instance().log("GeoNetworkingPort::user_map: timer ID is 0x%lx\n", (long)_timerid);
// Start the timer
unsigned int expiry = 1000; // One second
Params::const_iterator i = _layer_params.find("expiry");
if (i != _layer_params.cend()) {
expiry = static_cast<unsigned int>(std::strtoul(it->second.c_str(), NULL, 10));
}
_freq_nanosecs = 1000*1000000; // expiry time 1000ms
_its.it_value.tv_sec = _freq_nanosecs / 1000000000;
_its.it_value.tv_nsec = _freq_nanosecs % 1000000000;
_its.it_interval.tv_sec = _its.it_value.tv_sec;
_its.it_interval.tv_nsec = _its.it_value.tv_nsec;
if (timer_settime(_timerid, 0, &_its, NULL) == -1) {
loggers::get_instance().error("GeoNetworkingPort::user_map: Sigprocmask failure: %d", errno);
}
// Unlock the timer signal, so that timer notification can be delivered
loggers::get_instance().log("GeoNetworkingPort::user_map: Unblocking signal %d\n", SIGALRM);
if (sigprocmask(SIG_UNBLOCK, &_mask, NULL) == -1) {
loggers::get_instance().error("GeoNetworkingPort::user_map: Sigprocmask failure: %d", errno);
}
}*/
/*else { // _use_posix_timer
// TODO If timer mechanism is enought, remove fork code
if (_child > 0) { // Start beaconing if required
Params::const_iterator i = _layer_params.find(Params::beaconing);
if ((i != _layer_params.cend()) && (i->second.compare("1") == 0)) {
unsigned char *buffer = new unsigned char[it->second.length() + 1];
buffer[0] = 0x01;
copy(it->second.begin(), it->second.end(), buffer + 1);
write(_child_pids[1], buffer, it->second.length() + 1);
bool ack = false;
while (!ack) {
if ((read(_parent_pids[0], buffer, 1) > 0) && (buffer[0] == 0xAA)) {
loggers::get_instance().log("GeoNetworkingPort::user_map: Receive ack from child");
ack = true;
}
} // End of 'while' statement
delete [] buffer;
} else {
loggers::get_instance().log("GeoNetworkingPort::user_map: Beaconing not requested");
}
} // else, in child process
}*/
} else {
loggers::get_instance().error("GeoNetworkingPort::user_map: No layers defined in configuration file");
}
......@@ -151,18 +77,6 @@ namespace LibItsGeoNetworking__TestSystem {
{
loggers::get_instance().log(">>> GeoNetworkingPort::user_unmap: %s", system_port);
// Stop timer
/*if (_use_posix_timer) {
// Block timer signal temporarily
loggers::get_instance().log("GeoNetworkingPort::user_unmap: Blocking signal %d\n", SIGALRM);
sigemptyset(&_mask);
sigaddset(&_mask, SIGALRM);
if (sigprocmask(SIG_SETMASK, &_mask, NULL) == -1) {
loggers::get_instance().error("GeoNetworkingPort::user_map: Sigprocmask failure: %d", errno);
}
timer_delete(_timerid);
_timerid = 0;
}*/
// Reset layers
if (_layer != NULL) {
delete _layer;
......@@ -174,104 +88,12 @@ namespace LibItsGeoNetworking__TestSystem {
{
loggers::get_instance().log(">>> GeoNetworkingPort::user_start");
// TODO If timer mechanism is enought, remove fork code
/*if (!_use_posix_timer) { // Use fork
// Set up pipes for process communication
if (pipe2(_parent_pids, O_NONBLOCK) != 0) { // Failed to create pipe
loggers::get_instance().error("GeoNetworkingPort::user_start: Parent pipe creation failure: %d", errno);
}
if (pipe2(_child_pids, O_NONBLOCK) != 0) { // Failed to create pipe
loggers::get_instance().error("GeoNetworkingPort::user_start: Child pipe creation failure: %d", errno);
}
// Fork port for beaconing beacause of TITAN is not multithread at all :-(
// NOTE Need to fork process very early due to issues for handle dup operation
_child = fork();
if (_child == -1) { // Fork failure
close(_parent_pids[0]);
close(_parent_pids[1]);
close(_child_pids[0]);
close(_child_pids[1]);
loggers::get_instance().error("GeoNetworkingPort::user_start: Fork failure: %d", errno);
} else if (_child == 0) { // Child process
loggers::get_instance().log("GeoNetworkingPort::user_start: Child process is running");
// This is a hack
// All fds (except the pipe) should be closed in order to avoid some "funny" communication lost between the mctr and PTC
for (int i = 4; i < 128; i++) {
if (
(i != _parent_pids[0]) && (i != _parent_pids[1]) &&
(i != _child_pids[0]) && (i != _child_pids[1])
) {
if (dup(i) == EBADF) {
loggers::get_instance().log("GeoNetworkingPort::user_start: Child dup stops at %d - _layer=%p", i, _layer);
break;
}
}
} // End of 'for' statement
// Close _child_pids[1], down channel
close(_child_pids[1]);
_child_pids[1] = -1;
// Close _parent_pids[0], down channel
close(_parent_pids[0]);
_parent_pids[0] = -1;
process_background();
loggers::get_instance().log("GeoNetworkingPort::user_start: Child terminates");
std::_Exit(EXIT_SUCCESS);
} else { // Parent process
loggers::get_instance().log("GeoNetworkingPort::user_start: Parent process is running");
// Close _pids[0], up channel
close(_child_pids[0]);
_child_pids[0] = -1;
// Close _parent_pids[1], down channel
close(_parent_pids[1]);
_parent_pids[1] = -1;
unsigned char buffer[2];
bool ack = false;
while (!ack) {
if ((read(_parent_pids[0], buffer, 1) > 0) && (buffer[0] == 0xAA)) {
loggers::get_instance().log("GeoNetworkingPort::user_start: Receive ack from child");
ack = true;
}
} // End of 'while' statement
}
} else {
_child = -1;
}*/
} // End of user_start method
void GeoNetworkingPort::user_stop()
{
loggers::get_instance().log(">>> GeoNetworkingPort::user_stop");
// TODO If timer mechanism is enought, remove fork code
/*if (_child > 0) { // Parent process
// Terminate child process
loggers::get_instance().log("GeoNetworkingPort::user_stop: Stopping child process");
unsigned char buffer[] = { 0xFF };
write(_child_pids[1], buffer, 1);
// And wait for the child ack
bool ack = false;
while (!ack) {
if ((read(_parent_pids[0], buffer, 1) > 0) && (buffer[0] == 0xAA)) {
loggers::get_instance().log("GeoNetworkingPort::user_stop: Receive ack from child");
ack = true;
}
} // End of 'while' statement
// Wait child process
int status = -1;
waitpid(_child, &status, WNOHANG); // TODO Check returned code
loggers::get_instance().log("GeoNetworkingPort::user_stop: Child process ended [%d]", status);
// Close _parent_pids[1], up channel
close(_parent_pids[0]);
_parent_pids[0] = -1;
// Close _pids[1], down channel
close(_child_pids[1]);
_child_pids[1] = -1;
// Reset child pid
_child = -1;
}*/
} // End of user_stop method
void GeoNetworkingPort::outgoing_send(const GeoNetworkingReq& send_par)
......@@ -290,97 +112,9 @@ namespace LibItsGeoNetworking__TestSystem {
if (!p_ind.is_bound()) {
return;
}
// TODO If timer mechanism is enought, remove fork code
/*if (_child == 0) { // Bacgound task processing, ignore it
return;
*/
// Update location table
if (p_ind.msgIn().basicHeader().version() == 0) { // Non secured mode
const LibItsGeoNetworking__TypesAndValues::GnNonSecuredPacket& p = p_ind.msgIn().gnPacket().packet();
const LibItsGeoNetworking__TypesAndValues::HeaderTST& htst = p.commonHeader().headerTST();
if (htst.ischosen(LibItsGeoNetworking__TypesAndValues::HeaderTST::ALT_lsHdr)) { // Location service
const LibItsGeoNetworking__TypesAndValues::LsHeaderType& ls = htst.lsHdr();
if (ls.headerSubType() == LibItsGeoNetworking__TypesAndValues::HeaderSubTypeLs::e__lsReply) { // Update the Test System Location Table
const LibItsGeoNetworking__TypesAndValues::ExtendedHeader& ex = p.extendedHeader();
if (ex.ischosen(LibItsGeoNetworking__TypesAndValues::ExtendedHeader::ALT_lsReplyHeader)) {
const LibItsGeoNetworking__TypesAndValues::LongPosVector& sopv = ex.lsReplyHeader().srcPosVector();
loggers::get_instance().user_msg("GeoNetworkingPort::receive_msg: Update LocationTable: ", sopv);