Commit 59950133 authored by garciay's avatar garciay
Browse files

Add beaconing based on POSIX timer, alternatively based on fork (commented code)

parent 2d3af265
......@@ -7,6 +7,10 @@
// 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"
......@@ -14,17 +18,21 @@
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")
{
}
: 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)
{
......@@ -58,37 +66,213 @@ namespace LibItsGeoNetworking__TestSystem {
// Build layer stack
Params::iterator it = _cfg_params.find(std::string("params"));
if (it != _cfg_params.end()) {
//loggers::get_instance().log("GeoNetworkingPort::user_map: %s", it->second.c_str());
//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());
}
if (static_cast<GeoNetworkingLayer *>(_layer) == NULL) {
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");
}
//static_cast<GeoNetworkingLayer *>(_layer)->start_beaconing();
}
} // 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)
{
......@@ -106,6 +290,10 @@ 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
......@@ -129,5 +317,70 @@ namespace LibItsGeoNetworking__TestSystem {
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<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
} /* end of namespace */
......@@ -10,6 +10,10 @@
#ifndef GeoNetworkingPort_HH
#define GeoNetworkingPort_HH
/*#include <unistd.h>
#include <signal.h>
#include <time.h>*/
#include "LibItsGeoNetworking_TestSystem.hh"
#include "Layer.hh"
......@@ -22,14 +26,22 @@ namespace LibItsGeoNetworking__TestSystem {
Params _layer_params;
Layer * _layer;
std::string _time_key;
/*pid_t _child;
int _child_pids[2];
int _parent_pids[2];*/
/*bool _use_posix_timer; // TODO If timer mechanism is enought, remove fork code
timer_t _timerid;
struct sigevent _sev;
struct itimerspec _its;
long long _freq_nanosecs;
sigset_t _mask;
struct sigaction _sa;*/
public:
GeoNetworkingPort(const char *par_port_name = NULL);
~GeoNetworkingPort();
void set_parameter(const char *parameter_name,
const char *parameter_value);
void set_parameter(const char *parameter_name, const char *parameter_value);
void receiveMsg (const LibItsGeoNetworking__TestSystem::GeoNetworkingInd&, const Params&);
private:
......@@ -39,6 +51,10 @@ namespace LibItsGeoNetworking__TestSystem {
void Handle_Fd_Event_Writable(int fd);
void Handle_Fd_Event_Readable(int fd);
/* void Handle_Timeout(double time_since_last_call); */
//void process_background(); TODO If timer mechanism is enought, remove fork code
static void timer_irq_sigalrm_handler(int sig, siginfo_t *si, void *uc);
protected:
void user_map(const char *system_port);
void user_unmap(const char *system_port);
......
#include <thread>
#include <chrono>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "GeoNetworkingLayer.hh"
#include "GeoNetworkingTypes.hh"
......@@ -7,8 +11,9 @@
using namespace LibItsGeoNetworking__TypesAndValues;
GeoNetworkingLayer::GeoNetworkingLayer(const std::string & p_type, const std::string & param) : TLayer<LibItsGeoNetworking__TestSystem::GeoNetworkingPort>(p_type), _params(), _codec(), _beacon(NULL), _sendData() {
GeoNetworkingLayer::GeoNetworkingLayer(const std::string & p_type, const std::string & param) : TLayer<LibItsGeoNetworking__TestSystem::GeoNetworkingPort>(p_type), _params(), _codec(), _beacon(NULL), _sendData(), _timerid{0}, _sev{0}, _its{0}, _freq_nanosecs(0), _mask{0}, _sa{0} {
loggers::get_instance().log(">>> GeoNetworkingLayer::GeoNetworkingLayer: %s, %s", to_string().c_str(), param.c_str());
// Setup parameters
Params::convert(_params, param);
// Sanity checks
......@@ -33,10 +38,16 @@ GeoNetworkingLayer::GeoNetworkingLayer(const std::string & p_type, const std::st
_params.insert(std::pair<std::string, std::string>(std::string("mac_bc"), "FFFFFFFFFFFF"));
}
fill_beacon(latitude, longitude, ll_address);
Params::const_iterator i = _params.find(Params::beaconing);
if ((i != _params.cend()) && (i->second.compare("1") == 0)) {
start_beaconing();
}
} // End of constructor
GeoNetworkingLayer::~GeoNetworkingLayer() {
if (_timerid != 0) {
timer_delete(_timerid);
}
} // End of destructor
void GeoNetworkingLayer::sendMsg(const LibItsGeoNetworking__TestSystem::GeoNetworkingReq& p, Params& params) {
......@@ -103,8 +114,71 @@ void GeoNetworkingLayer::receiveData(OCTETSTRING& data, Params& params) {
toAllUpperPorts(p, params);
}
void GeoNetworkingLayer::start_beaconing() {
loggers::get_instance().log(">>> GeoNetworkingLayer::start_beaconing");
// Establish handler for timer signal
loggers::get_instance().log("GeoNetworkingLayer::start_beaconing: 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("GeoNetworkingLayer::start_beaconing: Sigaction failure: %d", errno);
}
// Block timer signal temporarily
loggers::get_instance().log("GeoNetworkingLayer::start_beaconing: Blocking signal %d\n", SIGALRM);
sigemptyset(&_mask);
sigaddset(&_mask, SIGALRM);
if (sigprocmask(SIG_SETMASK, &_mask, NULL) == -1) {
loggers::get_instance().error("GeoNetworkingLayer::start_beaconing: 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 GeoNetworkingLayer object address
if (timer_create(CLOCK_REALTIME, &_sev, &_timerid) == -1) {
loggers::get_instance().error("GeoNetworkingLayer::start_beaconing: Timer failure: %d", errno);
}
loggers::get_instance().log("GeoNetworkingLayer::start_beaconing: timer ID is 0x%lx\n", (long)_timerid);
// Start the timer
unsigned int expiry = 1000; // Default expiry time 1000ms
Params::const_iterator i = _params.find("expiry");
if (i != _params.cend()) {
expiry = static_cast<unsigned int>(std::strtoul(i->second.c_str(), NULL, 10));
}
_freq_nanosecs = expiry * 1000000;
_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("GeoNetworkingLayer::start_beaconing: Sigprocmask failure: %d", errno);
}
// Unlock the timer signal, so that timer notification can be delivered
loggers::get_instance().log("GeoNetworkingLayer::start_beaconing: Unblocking signal %d\n", SIGALRM);
if (sigprocmask(SIG_UNBLOCK, &_mask, NULL) == -1) {
loggers::get_instance().error("GeoNetworkingLayer::start_beaconing: Sigprocmask failure: %d", errno);
}
}
void GeoNetworkingLayer::stop_beaconing() {
loggers::get_instance().log(">>> GeoNetworkingLayer::stop_beaconing");
// Block timer signal temporarily
loggers::get_instance().log("GeoNetworkingLayer::stop_beaconing: Blocking signal %d\n", SIGALRM);
sigemptyset(&_mask);
sigaddset(&_mask, SIGALRM);
if (sigprocmask(SIG_SETMASK, &_mask, NULL) == -1) {
loggers::get_instance().error("GeoNetworkingLayer::stop_beaconing: Sigprocmask failure: %d", errno);
}
timer_delete(_timerid);
_timerid = 0;
}
void GeoNetworkingLayer::send_beacon() {
loggers::get_instance().log(">>> GeoNetworkingLayer::send_beacon");
ExtendedHeader* eh = static_cast<ExtendedHeader *>(_beacon->gnPacket().packet().extendedHeader().get_opt_value());
if (eh == NULL) {
loggers::get_instance().error("GeoNetworkingLayer::send_beacon: Wrong cast");
......@@ -170,8 +244,8 @@ void GeoNetworkingLayer::fill_beacon(INTEGER& p_latitude, INTEGER& p_longitude,
TrafficClass(
SCF(SCF::e__scfDisabled),
ChannelOffload(ChannelOffload::e__choffDisabled),
0
),
0
),
int2bit(0, 8),
0,
1,
......@@ -185,6 +259,13 @@ void GeoNetworkingLayer::fill_beacon(INTEGER& p_latitude, INTEGER& p_longitude,
// loggers::get_instance().log_msg("GeoNetworkingLayer::GeoNetworkingLayer: beacon value: ", *p._beacon);
}
void GeoNetworkingLayer::timer_irq_sigalrm_handler(int p_signal, siginfo_t *p_signal_info, void *p_uc) {
loggers::get_instance().log("GeoNetworkingLayer::timer_irq_sigalrm_handler: Caught signal %d\n", p_signal);
static_cast<GeoNetworkingLayer *>(p_signal_info->si_value.sival_ptr)->send_beacon();
} // End of method timer_irq_sigalrm_handler
class GeoNetworkingFactory: public LayerFactory {
static GeoNetworkingFactory _f;
public:
......
#ifndef GEONETWORKING_LAYER_H
#define GEONETWORKING_LAYER_H
#include <thread>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include <mutex>
#include "Layer.hh"
......@@ -22,11 +25,18 @@ class GeoNetworkingLayer : public TLayer<LibItsGeoNetworking__TestSystem::GeoNet
GeoNetworkingCodec _codec;
LibItsGeoNetworking__TypesAndValues::GeoNetworkingPdu* _beacon;
std::mutex _sendData; // FIXME To be removed, useless
timer_t _timerid;
struct sigevent _sev;
struct itimerspec _its;
long long _freq_nanosecs;
sigset_t _mask;
struct sigaction _sa;
void fill_beacon(INTEGER& p_latitude, INTEGER& p_longitude, OCTETSTRING& p_ll_address);
static void timer_irq_sigalrm_handler(int p_signal, siginfo_t *p_signal_info, void *p_uc);
public:
GeoNetworkingLayer() : TLayer<LibItsGeoNetworking__TestSystem::GeoNetworkingPort>(), _params(), _codec(), _beacon(NULL), _sendData() {};
GeoNetworkingLayer() : TLayer<LibItsGeoNetworking__TestSystem::GeoNetworkingPort>(), _params(), _codec(), _beacon(NULL), _sendData(), _timerid{0}, _sev{0}, _its{0}, _freq_nanosecs(0), _mask{0}, _sa{0} { };
GeoNetworkingLayer(const std::string& p_type, const std::string& param);
virtual ~GeoNetworkingLayer();
......@@ -35,6 +45,8 @@ public:
virtual void sendData(OCTETSTRING& data, Params& params);
virtual void receiveData(OCTETSTRING& data, Params& params);
void start_beaconing();
void stop_beaconing();
void send_beacon();
};
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment