// This Test Port skeleton source file was generated by the // TTCN-3 Compiler of the TTCN-3 Test Executor version CRL 113 200/5 R3A // for U-ERICSSON\ethgry (ethgry@HU00078339) on Sat Aug 15 22:33:04 2015 // Copyright Ericsson Telecom AB 2000-2014 // You may modify this file. Complete the body of empty functions and // add your member functions here. /*#include #include #include */ #include "GeoNetworkingPort.hh" #include "GeoNetworkingLayer.hh" #include "loggers.hh" 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}*/ { // Nothing to do } // End of constructor GeoNetworkingPort::~GeoNetworkingPort() { loggers::get_instance().log(">>> GeoNetworkingPort::~GeoNetworkingPort"); /*if (_use_posix_timer && (_timerid != 0)) { timer_delete(_timerid); }*/ if (_layer != NULL) { delete _layer; } } // End of destructor void GeoNetworkingPort::set_parameter(const char * parameter_name, const char * parameter_value) { loggers::get_instance().log("GeoNetworkingPort::set_parameter: %s=%s", parameter_name, parameter_value); _cfg_params.insert(std::pair(std::string(parameter_name), std::string(parameter_value))); } /*void GeoNetworkingPort::Handle_Fd_Event(int fd, boolean is_readable, boolean is_writable, boolean is_error) {}*/ void GeoNetworkingPort::Handle_Fd_Event_Error(int /*fd*/) { } void GeoNetworkingPort::Handle_Fd_Event_Writable(int /*fd*/) { } void GeoNetworkingPort::Handle_Fd_Event_Readable(int /*fd*/) { } /*void GeoNetworkingPort::Handle_Timeout(double time_since_last_call) {}*/ void GeoNetworkingPort::user_map(const char * system_port) { loggers::get_instance().log(">>> GeoNetworkingPort::user_map: %s", system_port); // Build layer stack Params::iterator it = _cfg_params.find(std::string("params")); if (it != _cfg_params.end()) { //loggers::get_instance().log("GeoNetworkingPort::user_map<%d>: %s", _child, it->second.c_str()); // Setup parameters Params::convert(_layer_params, it->second); // Create layer _layer = LayerStackBuilder::GetInstance()->createLayerStack(it->second.c_str()); if (static_cast(_layer) == NULL) { loggers::get_instance().error("GeoNetworkingPort::user_map: Invalid stack configuration: %s", it->second.c_str()); } static_cast(_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(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"); } } // End of user_map method void GeoNetworkingPort::user_unmap(const char * system_port) { 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; _layer = NULL; } } // End of user_unmap method void GeoNetworkingPort::user_start() { 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) { loggers::get_instance().log_msg(">>> GeoNetworkingPort::outgoing_send: payload=", send_par); float duration; loggers::get_instance().set_start_time(_time_key); static_cast(_layer)->sendMsg(send_par, _layer_params); loggers::get_instance().set_stop_time(_time_key, duration); } void GeoNetworkingPort::receiveMsg (const LibItsGeoNetworking__TestSystem::GeoNetworkingInd& p_ind, const Params& p_params) { loggers::get_instance().log_msg(">>> GeoNetworkingPort::receive_msg: ", p_ind); // Sanity check 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); // TODO Add a LocationTable class to manage it } // else, discard packet } // else, discard packet } // else, discard packet } // TODO else security mode // TODO Add beacon filter for StartPassBeaconing/Stop incoming_message(p_ind); } // TODO If timer mechanism is enought, remove fork code /*void GeoNetworkingPort::process_background() { loggers::get_instance().log(">>> GeoNetworkingPort::process_background"); std::chrono::milliseconds expiry(1000); // Default is set to 1 second unsigned long long ms; unsigned char buffer[512]; bool terminate = false; // Child process ready, send an ack (0xAA) buffer[0] = 0xAA; write(_parent_pids[1], buffer, 1); while (!terminate) { int result = read(_child_pids[0], buffer, 512); if (result > 0) { loggers::get_instance().log("GeoNetworkingPort::process_background: receive %d bytes", result); OCTETSTRING os(result, buffer); // TODO For debug, to be removed loggers::get_instance().log_to_hexa("GeoNetworkingPort::process_background: ", os); // Decode it switch (buffer[0]) { case 0x01: { std::string s((const char *)(buffer + 1), result - 1); loggers::get_instance().log("GeoNetworkingPort::process_background: %s", s.c_str()); _layer = LayerStackBuilder::GetInstance()->createLayerStack(s.c_str()); static_cast(_layer)->addUpperPort(this); } break; case 0xFF: terminate = true; break; default: // Discard it break; } // End of 'switch' statement buffer[0] = 0xAA; write(_parent_pids[1], buffer, 1); } if (_layer != NULL) { static_cast(_layer)->send_beacon(); // Timer ms = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count() + expiry.count(); loggers::get_instance().log("GeoNetworkingPort::process_background: Start timer: %ld", ms); while (ms > static_cast(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count())); loggers::get_instance().log("GeoNetworkingPort::process_background: After timer"); } } // End of 'while' statement if (_layer != NULL) { delete _layer; _layer = NULL; } // Close _pids[1], up channel close(_child_pids[0]); _child_pids[0] = -1; // Close _parent_pids[1], down channel close(_parent_pids[1]); _parent_pids[1] = -1; loggers::get_instance().log("<<< GeoNetworkingPort::process_background"); } */// End of process_background method /*void GeoNetworkingPort::timer_irq_sigalrm_handler(int sig, siginfo_t *si, void *uc) { loggers::get_instance().log("GeoNetworkingPort::timer_irq_sigalrm_handler: Caught signal %d\n", sig); static_cast(static_cast(si->si_value.sival_ptr)->_layer)->send_beacon(); }*/ // End of method timer_irq_sigalrm_handler } /* end of namespace */