Newer
Older
#include <thread>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "GeoNetworkingLayer.hh"
#include "GeoNetworkingTypes.hh"
#include "loggers.hh"
GeoNetworkingLayer::GeoNetworkingLayer(const std::string & p_type, const std::string & param) : TLayer<LibItsGeoNetworking__TestSystem::GeoNetworkingPort>(p_type), _params(), _codec(), _beacon(NULL), _location_table(), _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());
// Sanity checks
INTEGER latitude;
Params::const_iterator it = _params.find(Params::latitude);
if (it != _params.cend()) {
latitude = str2int(CHARSTRING(it->second.c_str()));
}
INTEGER longitude;
it = _params.find(Params::longitude);
if (it != _params.cend()) {
longitude = str2int(CHARSTRING(it->second.c_str()));
}
OCTETSTRING ll_address;
it = _params.find(Params::ll_address);
if (it != _params.cend()) {
ll_address = str2oct(CHARSTRING(it->second.c_str()));
}
// Add broadcast address if needed
it = _params.find("mac_bc");
if (it == _params.cend()) {
_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)) { // Immediate beaconing was requested
start_beaconing();
}
} // End of constructor
if (_timerid != 0) {
timer_delete(_timerid);
}
} // End of destructor
void GeoNetworkingLayer::sendMsg(const LibItsGeoNetworking__TestSystem::GeoNetworkingReq& p, Params& params) {
void GeoNetworkingLayer::sendData(OCTETSTRING& data, Params& params) {
loggers::get_instance().log_msg(">>> GeoNetworkingLayer::sendData: ", data);
while (_sendData.try_lock() == FALSE) {
// not ready yet
std::this_thread::sleep_for(std::chrono::milliseconds(1));
} // End of 'while' statement
_sendData.unlock();
loggers::get_instance().log("<<< GeoNetworkingLayer::sendData");
void GeoNetworkingLayer::receiveData(OCTETSTRING& data, Params& params) {
loggers::get_instance().log_msg(">>> GeoNetworkingLayer::receiveData: ", data);
77
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
LibItsGeoNetworking__TestSystem::GeoNetworkingInd ind;
_codec.decode(data, ind.msgIn(), ¶ms);
// Update GeoNetworking layer
if (ind.msgIn().basicHeader().version() == 0) { // Non secured mode
const LibItsGeoNetworking__TypesAndValues::LongPosVector* sopv = nullptr;
const LibItsGeoNetworking__TypesAndValues::GnNonSecuredPacket& p = ind.msgIn().gnPacket().packet();
const LibItsGeoNetworking__TypesAndValues::HeaderTST& htst = p.commonHeader().headerTST();
if (p.extendedHeader().ispresent()) { // Update location table
const LibItsGeoNetworking__TypesAndValues::ExtendedHeader& ex = p.extendedHeader();
if (htst.ischosen(LibItsGeoNetworking__TypesAndValues::HeaderTST::ALT_beaconHdr)) { // Receive a beacon
sopv = &ex.beaconHeader().srcPosVector();
} else if (htst.ischosen(LibItsGeoNetworking__TypesAndValues::HeaderTST::ALT_tsbHdr)) { // Receive a topologicallyScopeBroadcast
if (ex.ischosen(LibItsGeoNetworking__TypesAndValues::ExtendedHeader::ALT_tsbHeader)) {
sopv = &ex.tsbHeader().srcPosVector();
} else {
sopv = &ex.shbHeader().srcPosVector();
}
} else if (htst.ischosen(LibItsGeoNetworking__TypesAndValues::HeaderTST::ALT_geoBroadcastHdr)) {
sopv = &ex.geoBroadcastHeader().srcPosVector();
} else if (htst.ischosen(LibItsGeoNetworking__TypesAndValues::HeaderTST::ALT_lsHdr)) { // Receive a location service
if (ex.ischosen(LibItsGeoNetworking__TypesAndValues::ExtendedHeader::ALT_lsRequestHeader)) { // Receive a LocationService/LsRequest
sopv = &ex.lsRequestHeader().srcPosVector();
// TODO Send LsReply if we are not in context of GN ATS
} else {
sopv = &ex.lsReplyHeader().srcPosVector();
}
} else if (htst.ischosen(LibItsGeoNetworking__TypesAndValues::HeaderTST::ALT_geoAnycastHdr)) { // Receive a GeoAnycast
sopv = &ex.geoAnycastHeader().srcPosVector();
} else if (htst.ischosen(LibItsGeoNetworking__TypesAndValues::HeaderTST::ALT_geoUnicastHdr)) {
sopv = &ex.geoUnicastHeader().srcPosVector();
/*} else if (htst.ischosen(LibItsGeoNetworking__TypesAndValues::HeaderTST::ALT_saHdr)) { // Receive Service Advertisement
if (ex.ischosen(LibItsGeoNetworking__TypesAndValues::ExtendedHeader::ALT_xxx)) {
sopv = &ex.xxxHeader().srcPosVector();
} else {
sopv = &ex.xxxHeader().srcPosVector();
}*/
} // else, nothing to do
loggers::get_instance().log("GeoNetworkingLayer::receiveData: sopv is boud: %d", sopv->is_bound());
if(sopv->is_bound()) {
const LibItsGeoNetworking__TypesAndValues::LongPosVector& lpv = *sopv;
_location_table.add_entry(lpv);
}
}
// TODO Add beacon filter for StartPassBeaconing/Stop
// By default incoming beacons are filtered by the test adapter
if (htst.ischosen(LibItsGeoNetworking__TypesAndValues::HeaderTST::ALT_beaconHdr)) { // Discard beacon
return;
}
} // TODO else security mode, becarfull to duplicate code
loggers::get_instance().log("GeoNetworkingLayer::receiveData: dst=%s", it->second.c_str());
ind.macDestinationAddress() = str2oct(CHARSTRING(it->second.c_str()));
ind.macDestinationAddress() = str2oct(CHARSTRING(_params["mac_bc"].c_str()));
}
// 2. ssp
it = params.find(Params::ssp);
if (it != params.cend()) {
loggers::get_instance().log("GeoNetworkingLayer::receiveData: ssp=%s", it->second.c_str());
// 3. its_aid
it = params.find(Params::its_aid);
if (it != params.cend()) {
loggers::get_instance().log("GeoNetworkingLayer::receiveData: its_aid=%s", it->second.c_str());
// Pass the GeoNetworking raw payload to the upper layers if any
it = params.find(Params::gn_payload);
if (it != params.cend()) {
loggers::get_instance().log("GeoNetworkingLayer::receiveData: gn_payload=%s", it->second.c_str());
OCTETSTRING os(str2oct(CHARSTRING(it->second.c_str())));
receiveToAllLayers(os, params);
} else {
loggers::get_instance().warning("GeoNetworkingLayer::receiveData: No payload to pass to upper layers");
}
// Pass it to the ports
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", _signal_id);
_sa.sa_flags = SA_SIGINFO;
_sa.sa_sigaction = timer_irq_sigalrm_handler;
sigemptyset(&_sa.sa_mask);
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", _signal_id);
sigemptyset(&_mask);
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_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", _signal_id);
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", _signal_id);
sigemptyset(&_mask);
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());
loggers::get_instance().error("GeoNetworkingLayer::send_beacon: Wrong cast");
// Update timestamp
unsigned long long ms = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count() - 1072911600000L; // TODO Add method such as its_tme() & its_time_mod()
eh->beaconHeader().srcPosVector().timestamp__().set_long_long_val(static_cast<unsigned int>(ms));
//loggers::get_instance().log_msg("GeoNetworkingLayer::send_beacon: ", *_beacon);
// Encode message using TITAN because of payload in omited
TTCN_Buffer encoding_buffer;
_beacon->encode(*(_beacon->get_descriptor()), encoding_buffer, TTCN_EncDec::CT_RAW);
OCTETSTRING data(encoding_buffer.get_len(), encoding_buffer.get_data());
// Send it
Params params(_params);
sendData(data, params);
//loggers::get_instance().log("<<< GeoNetworkingLayer::send_beacon");
} // End of send_beacon method
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
void GeoNetworkingLayer::fill_beacon(INTEGER& p_latitude, INTEGER& p_longitude, OCTETSTRING& p_ll_address)
{
_beacon = new GeoNetworkingPdu();
HeaderTST h;
h.beaconHdr() = BeaconHeaderType(
HeaderType(HeaderType::e__beacon),
0
);
ExtendedHeader eh;
eh.beaconHeader() = BeaconHeader(
LongPosVector(
GN__Address(
TypeOfAddress(TypeOfAddress::e__manual),
StationType(StationType::e__roadSideUnit),
33,
p_ll_address
),
0,
p_latitude,
p_longitude,
int2bit(0, 1),
0,
0
)
);
_beacon->basicHeader() = BasicHeader(
0,
BasicNextHeader(
BasicNextHeader::e__commonHeader
),
0,
Lifetime(
4,
LtBase(LtBase::e__50ms)
),
5
);
_beacon->gnPacket().packet() = GnNonSecuredPacket(
CommonHeader(
NextHeader(
NextHeader::e__any
),
0,
h,
TrafficClass(
SCF(SCF::e__scfDisabled),
ChannelOffload(ChannelOffload::e__choffDisabled),
0
),
int2bit(0, 8),
0,
1,
0
),
OPTIONAL<ExtendedHeader>(eh),
OPTIONAL<GnRawPayload>()
);
_beacon->gnPacket().packet().payload().set_to_omit();
_beacon->gnPacket().securedMsg().set_to_omit();
// 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", 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 {
GeoNetworkingFactory();
virtual Layer * createLayer(const std::string & type,
const std::string & param);
};
GeoNetworkingFactory::GeoNetworkingFactory() {
// Register factory
loggers::get_instance().log(">>> GeoNetworkingFactory::GeoNetworkingFactory");
LayerStackBuilder::RegisterLayerFactory("GN", this);
}
Layer * GeoNetworkingFactory::createLayer(const std::string & type, const std::string & param) {
}
GeoNetworkingFactory GeoNetworkingFactory::_f;