Newer
Older
// 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 <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>*/
namespace LibItsGeoNetworking__TestSystem {
: 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
loggers::get_instance().log(">>> GeoNetworkingPort::~GeoNetworkingPort");
/*if (_use_posix_timer && (_timerid != 0)) {
timer_delete(_timerid);
}*/
} // 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, std::string>(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_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);
//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<GeoNetworkingLayer *>(_layer) == NULL) {
loggers::get_instance().error("GeoNetworkingPort::user_map: Invalid stack configuration: %s", it->second.c_str());
}
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/*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
}*/
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
} // End of user_unmap method
loggers::get_instance().log(">>> GeoNetworkingPort::user_start");
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
// 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
loggers::get_instance().log(">>> GeoNetworkingPort::user_stop");
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
// 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<GeoNetworkingLayer *>(_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
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
// 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<GeoNetworkingLayer *>(_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<GeoNetworkingLayer *>(_layer)->send_beacon();
// Timer
ms = std::chrono::duration_cast<std::chrono::milliseconds>(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<unsigned long long>(std::chrono::duration_cast<std::chrono::milliseconds>(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<GeoNetworkingLayer *>(static_cast<GeoNetworkingPort *>(si->si_value.sival_ptr)->_layer)->send_beacon();
}*/ // End of method timer_irq_sigalrm_handler