Newer
Older
#include <thread>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
using namespace LibItsGeoNetworking__TypesAndValues;
geonetworking_layer::geonetworking_layer(const std::string & p_type, const std::string & p_param) : t_layer<LibItsGeoNetworking__TestSystem::GeoNetworkingPort>(p_type), _params(), _codec(), _beacon(nullptr), _gbc_packet(nullptr), _shb_packet(nullptr), _tsb_packet(nullptr), _ls_reply(nullptr), _location_table(), _pass_beacon_table(), _device_mode{false}, _secured_mode{false}, _encrypted_mode{false}, _enable_security_checks{false}, _sendData(), _timerid{0}, _sev{0}, _its{0}, _freq_nanosecs(0), _mask{0}, _sa{0}, _sequence_number{0}, _latitude{0}, _longitude{0} {
loggers::get_instance().log(">>> geonetworking_layer::geonetworking_layer: %s, %s", to_string().c_str(), p_param.c_str());
init(p_type, p_param);
} // End of constructor
geonetworking_layer::~geonetworking_layer() {
loggers::get_instance().log(">>> geonetworking_layer::~geonetworking_layer");
if (_timerid != 0) {
timer_delete(_timerid);
}
if (_beacon != nullptr) {
delete _beacon;
}
if (_gbc_packet != nullptr) {
delete _gbc_packet;
}
if (_shb_packet != nullptr) {
delete _shb_packet;
}
if (_ls_reply != nullptr) {
delete _ls_reply;
}
} // End of destructor
void geonetworking_layer::init(const std::string & p_type, const std::string & p_param) {
loggers::get_instance().log(">>> geonetworking_layer::init: %s, %s", to_string().c_str(), p_param.c_str());
params::convert(_params, p_param);
params::const_iterator it = _params.find(params::latitude);
_latitude = converter::get_instance().string_to_int(it->second);
_longitude = converter::get_instance().string_to_int(it->second);
if (it != _params.cend()) {
ll_address = str2oct(CHARSTRING(it->second.c_str()));
}
INTEGER distanceA = 1000; // 1km
distanceA = converter::get_instance().string_to_int(it->second);
distanceB = converter::get_instance().string_to_int(it->second);
angle = converter::get_instance().string_to_int(it->second);
INTEGER station_type = 5; // passangerCar
if (it != _params.cend()) {
station_type = converter::get_instance().string_to_int(it->second);
}
INTEGER country = 0;
if (it != _params.cend()) {
country = converter::get_instance().string_to_int(it->second);
}
INTEGER type_of_address = 1; // Manual
if (it != _params.cend()) {
type_of_address = converter::get_instance().string_to_int(it->second);
}
_device_mode = (1 == converter::get_instance().string_to_int(it->second));
if (it != _params.cend()) {
_secured_mode = (1 == converter::get_instance().string_to_int(it->second));
} else {
_params.insert(std::pair<std::string, std::string>(std::string("secured_mode"), "0"));
if (it != _params.cend()) {
_encrypted_mode = (1 == converter::get_instance().string_to_int(it->second));
} else {
_params.insert(std::pair<std::string, std::string>(std::string("encrypted_mode"), "0"));
it = _params.find(params::enable_security_checks);
if (it != _params.cend()) {
_enable_security_checks = (1 == converter::get_instance().string_to_int(it->second));
}
_params.insert(std::pair<std::string, std::string>(std::string("its_aid"), "141"));
if (it == _params.cend()) {
_params.insert(std::pair<std::string, std::string>(std::string("mac_bc"), "FFFFFFFFFFFF"));
}
if (_secured_mode || _encrypted_mode) {
loggers::get_instance().log("geonetworking_layer::geonetworking_layer: Setup secured mode");
fill_beacon(ll_address, station_type, country, type_of_address);
params::const_iterator i = _params.find(params::beaconing);
if ((i != _params.cend()) && (i->second.compare("1") == 0)) { // Immediate beaconing was requested
// Prepare beaconing operation
start_beaconing();
}
fill_gbc_packet(ll_address, _latitude, _longitude, distanceA, distanceB, angle);// TODO Check if GeoBroadcastArea lat/lon are identical to lat/lon of the Test System
fill_shb_packet(ll_address);
fill_tsb_packet(ll_address);
fill_ls_reply(ll_address);
// Register this object for AdapterControlPort
loggers::get_instance().log("geonetworking_layer::geonetworking_layer: Register %s/%p", p_type.c_str(), this);
registration<geonetworking_layer>::get_instance().add_item(p_type, this);
// Add 4 leap seconds to convert to TAI (as Feb 2019)
base_time::get_instance().set_leap_delay_us(4 * 1000000); // TODO Set it as parameter
} // End of init_params
void geonetworking_layer::sendMsg(const LibItsGeoNetworking__TestSystem::GeoNetworkingReq& p, params& params) {
loggers::get_instance().log(">>> geonetworking_layer::sendMsg");
// Encode GeoNetworking PDU
OCTETSTRING data;
_codec.encode(p.msgOut(), data);
void geonetworking_layer::send_data(OCTETSTRING& data, params& params) {
loggers::get_instance().log_msg(">>> geonetworking_layer::send_data: ", data);
if (_device_mode) { // Need to build a GN packet
params[params::certificate] = _params[params::certificate];
params[params::hash] = _params[params::hash];
params[params::signature] = _params[params::signature]; // TODO Should be removed
if (build_geonetworking_pdu(data, params) != 0) {
// TODO To be removed
while (_sendData.try_lock() == FALSE) {
// not ready yet
std::this_thread::sleep_for(std::chrono::milliseconds(1));
} // End of 'while' statement
loggers::get_instance().log("<<< geonetworking_layer::send_data");
const TTCN_RAWdescriptor_t _intx_raw_= {RAW_INTX,SG_NO,ORDER_MSB,ORDER_MSB,ORDER_LSB,ORDER_MSB,EXT_BIT_NO,ORDER_LSB,ORDER_LSB,TOP_BIT_INHERITED,0,0,0,8,0,NULL,-1,CharCoding::UNKNOWN};
const TTCN_Typedescriptor_t _intx_descr_={"IntX", NULL, &_intx_raw_, NULL, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE};
void geonetworking_layer::receive_data(OCTETSTRING& data, params& params) {
loggers::get_instance().log_msg(">>> geonetworking_layer::receive_data: ", data);
LibItsGeoNetworking__TypesAndValues::BasicHeader basic_header;
decode_basic_header(data, basic_header);
if ((int)basic_header.nextHeader() == 2) { // Verify and extract the GeoNetworking Secured Packet as specified in ETSI EN 302 636-4-1 V1.3.1 (2017-08) Clause 9.6.1 Composition of the Basic Header
unsigned int basic_header_len = 4;// FIXME How to retrive the BasicHeader length basic_header.get_descriptor()->raw->fieldlength / 8;
loggers::get_instance().log("geonetworking_layer::receive_data: basic_header_len = %d", basic_header_len);
// Verify and extract the GeoNetworking Secured Packet as specified in ETSI EN 302 636-4-1 V1.3.1 (2017-08) Clause 9.4 GeoNetworking Secured Packet
OCTETSTRING unsecured_gn_payload;
OCTETSTRING secured_data = OCTETSTRING(data.lengthof() - basic_header_len, static_cast<const unsigned char*>(data) + basic_header_len);
if (*static_cast<const unsigned char*>(secured_data) == 0x02) { // This is the old Security version format, discard it
loggers::get_instance().warning("geonetworking_layer::receive_data: Security error");
if (_enable_security_checks) {
return;
}
INTEGER n; int r;
TTCN_Buffer buf(secured_data);
loggers::get_instance().warning("geonetworking_layer::receive_data: Old security format, parse manualy");
buf.increase_pos(1); // skip version
n.decode(_intx_descr_, buf, TTCN_EncDec::CT_RAW);
if(n > (int)buf.get_read_len()){
loggers::get_instance().warning("geonetworking_layer::receive_data: Broken security headers");
return;
}
buf.increase_pos((int)n); // skip headers
// payload type
r = *buf.get_read_data();
buf.increase_pos(1);
if(r != 3){
n.decode(_intx_descr_, buf, TTCN_EncDec::CT_RAW);
//payload length
if(n > (int)buf.get_read_len()){
loggers::get_instance().warning("geonetworking_layer::receive_data: Broken security payload");
return;
}
unsecured_gn_payload = OCTETSTRING(n, buf.get_read_data());
}
///////////////////
if (security_services::get_instance().verify_and_extract_gn_payload(secured_data, _enable_security_checks, ieee_1609dot2_data, unsecured_gn_payload, params) != 0) {
loggers::get_instance().warning("geonetworking_layer::receive_data: Security error");
if (_enable_security_checks) {
return;
}
loggers::get_instance().log_msg("geonetworking_layer::receive_data: Unsecured payload: ", unsecured_gn_payload);
data = OCTETSTRING(basic_header_len, static_cast<const unsigned char*>(data)) + unsecured_gn_payload;
loggers::get_instance().log_msg("geonetworking_layer::receive_data: Geonetworking payload to decode: ", data);
LibItsGeoNetworking__TestSystem::GeoNetworkingInd ind;
_codec.decode(data, ind.msgIn(), ¶ms);
// Update optional securedMsg field if required
if (ieee_1609dot2_data.is_bound()) {
ind.msgIn().gnPacket().securedMsg() = OPTIONAL<IEEE1609dot2::Ieee1609Dot2Data>(ieee_1609dot2_data);
} // else, nothing to do
// Update context
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 in case of non GN test suite
if (_device_mode) {
// Update _ls_reply
ExtendedHeader* eh = static_cast<ExtendedHeader *>(_ls_reply->gnPacket().packet().extendedHeader().get_opt_value());
if (eh != nullptr) {
// Update sequence number
eh->lsReplyHeader().seqNumber() = _sequence_number++;
// Update destination
eh->lsReplyHeader().dstPosVector().gnAddr() = sopv->gnAddr();
eh->lsReplyHeader().dstPosVector().latitude() = sopv->latitude();
eh->lsReplyHeader().dstPosVector().longitude() = sopv->longitude();
// Update timestamp
eh->lsReplyHeader().srcPosVector().timestamp__().set_long_long_val(base_time::get_instance().get_its_current_time_mod_ms());
eh->lsReplyHeader().dstPosVector().timestamp__() = eh->lsReplyHeader().srcPosVector().timestamp__();
loggers::get_instance().log_msg("geonetworking_layer::receive_data: ", *_ls_reply);
// send it
// Encode GeoNetworking PDU
OCTETSTRING os;
_codec.encode(*_ls_reply, os);
if (build_secured_pdu(data, _params) != 0) {
// Send it
// TODO To be removed
while (_sendData.try_lock() == FALSE) {
// not ready yet
std::this_thread::sleep_for(std::chrono::milliseconds(1));
} // End of 'while' statement
loggers::get_instance().error("geonetworking_layer::send_data: Wrong cast");
} 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, nothing to do
loggers::get_instance().log("geonetworking_layer::receive_data: sopv is bound: %d", sopv->is_bound());
if(sopv->is_bound()) {
const LibItsGeoNetworking__TypesAndValues::LongPosVector& lpv = *sopv;
_location_table.add_entry(lpv);
}
}
// By default incoming beacons are filtered by the test adapter
if (htst.ischosen(LibItsGeoNetworking__TypesAndValues::HeaderTST::ALT_beaconHdr)) {
loggers::get_instance().log_msg("geonetworking_layer::receive_data: Pass beaconing filtering: ", sopv->gnAddr().mid());
if (_pass_beacon_table.empty()) { // Discard beacon
loggers::get_instance().log("geonetworking_layer::receive_data: Pass beaconing table empty, discard it");
return;
} else { // Check beacon filter for StartPassBeaconing/Stop
if (!_pass_beacon_table.has_entry(sopv->gnAddr().mid())) { // Discard beacon
loggers::get_instance().log_msg("geonetworking_layer::receive_data: Not in pass beaconing table, discard it", *sopv);
return;
} // else, continue
}
} // else, continue
} else {
// Inavlid GeoNetworking payload, discard it
loggers::get_instance().warning("geonetworking_layer::receive_data: Failed to decode payload, discard it");
// Add lower layers parameters
// 1. Destination MAC address
params::const_iterator it = params.find(params::mac_dst);
loggers::get_instance().log("geonetworking_layer::receive_data: dst=%s", it->second.c_str());
ind.macDestinationAddress() = str2oct(CHARSTRING(it->second.c_str()));
} else {
ind.macDestinationAddress() = str2oct(CHARSTRING(_params["mac_bc"].c_str()));
}
// 2. ssp
loggers::get_instance().log("geonetworking_layer::receive_data: ssp=%s", it->second.c_str());
ind.ssp() = oct2bit(str2oct(CHARSTRING(it->second.c_str())));
} else {
ind.ssp().set_to_omit();
}
// 3. its_aid
loggers::get_instance().log("geonetworking_layer::receive_data: its_aid=%s", it->second.c_str());
ind.its__aid() = std::stoi(it->second.c_str());
} else {
ind.its__aid().set_to_omit();
}
// Pass the GeoNetworking raw payload to the upper layers if any
loggers::get_instance().log("geonetworking_layer::receive_data: gn_payload=%s", it->second.c_str());
OCTETSTRING os(str2oct(CHARSTRING(it->second.c_str())));
loggers::get_instance().warning("geonetworking_layer::receive_data: No payload to pass to upper layers");
OCTETSTRING geonetworking_layer::trigger_ac_event(OCTETSTRING& data, params& params)
loggers::get_instance().log_to_hexa(">>> geonetworking_layer::trigger_ac_event: ", data);
return int2oct(0, 2);
} // End of trigger_ac_event method
void geonetworking_layer::start_beaconing() {
loggers::get_instance().log(">>> geonetworking_layer::start_beaconing");
//loggers::get_instance().log_msg("geonetworking_layer::start_beaconing: _beacon=", *_beacon);
// Establish handler for timer signal
loggers::get_instance().log("geonetworking_layer::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);
if (sigaction(_signal_id, &_sa, nullptr) == -1) {
loggers::get_instance().error("geonetworking_layer::start_beaconing: Sigaction failure: %d", errno);
}
// Block timer signal temporarily
loggers::get_instance().log("geonetworking_layer::start_beaconing: Blocking signal %d\n", _signal_id);
sigemptyset(&_mask);
sigaddset(&_mask, _signal_id);
if (sigprocmask(SIG_SETMASK, &_mask, nullptr) == -1) {
loggers::get_instance().error("geonetworking_layer::start_beaconing: Sigprocmask failure: %d", errno);
}
// Create the timer
_sev.sigev_notify = SIGEV_SIGNAL;
_sev.sigev_signo = _signal_id; // Use signal alarm
_sev.sigev_value.sival_ptr = this; // The geonetworking_layer object address
if (timer_create(CLOCK_REALTIME, &_sev, &_timerid) == -1) {
loggers::get_instance().error("geonetworking_layer::start_beaconing: Timer failure: %d", errno);
loggers::get_instance().log("geonetworking_layer::start_beaconing: timer ID is 0x%x\n", (long)_timerid);
// Start the timer
unsigned int expiry = 1000; // Default expiry time 1000ms
params::const_iterator i = _params.find("expiry");
expiry = static_cast<unsigned int>(std::strtoul(i->second.c_str(), nullptr, 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, nullptr) == -1) {
loggers::get_instance().error("geonetworking_layer::start_beaconing: Sigprocmask failure: %d", errno);
}
// Unlock the timer signal, so that timer notification can be delivered
loggers::get_instance().log("geonetworking_layer::start_beaconing: Unblocking signal %d\n", _signal_id);
if (sigprocmask(SIG_UNBLOCK, &_mask, nullptr) == -1) {
loggers::get_instance().error("geonetworking_layer::start_beaconing: Sigprocmask failure: %d", errno);
}
} // End of start_beaconing method
void geonetworking_layer::start_beaconing(const LibItsGeoNetworking__TypesAndValues::GeoNetworkingPdu& p_beacon) {
loggers::get_instance().log_msg(">>> geonetworking_layer::start_beaconing", p_beacon);
// Initialize the beacon
if (_beacon != nullptr) {
delete _beacon;
}
_beacon = new LibItsGeoNetworking__TypesAndValues::GeoNetworkingPdu(p_beacon);
start_beaconing(); // TODO Refined adding a boolean return code
} // End of start_beaconing method
void geonetworking_layer::stop_beaconing() {
loggers::get_instance().log(">>> geonetworking_layer::stop_beaconing");
loggers::get_instance().log("geonetworking_layer::stop_beaconing: Blocking signal %d\n", _signal_id);
sigemptyset(&_mask);
sigaddset(&_mask, _signal_id);
if (sigprocmask(SIG_SETMASK, &_mask, nullptr) == -1) {
loggers::get_instance().error("geonetworking_layer::stop_beaconing: Sigprocmask failure: %d", errno);
}
timer_delete(_timerid);
_timerid = 0;
} // End of stop_beaconing method
void geonetworking_layer::send_beacon() {
loggers::get_instance().log(">>> geonetworking_layer::send_beacon");
ExtendedHeader* eh = static_cast<ExtendedHeader *>(_beacon->gnPacket().packet().extendedHeader().get_opt_value());
loggers::get_instance().error("geonetworking_layer::send_beacon: Wrong cast");
eh->beaconHeader().srcPosVector().timestamp__().set_long_long_val((unsigned int)base_time::get_instance().get_its_current_time_mod_ms());
//loggers::get_instance().log_msg("geonetworking_layer::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());
if (build_secured_pdu(data, _params) != 0) {
// TODO To be removed
while (_sendData.try_lock() == FALSE) {
// not ready yet
std::this_thread::sleep_for(std::chrono::milliseconds(1));
} // End of 'while' statement
//loggers::get_instance().log("<<< geonetworking_layer::send_beacon");
void geonetworking_layer::start_pass_beaconing(const LibItsGeoNetworking__TypesAndValues::BeaconHeader& p_beacon) {
loggers::get_instance().log_msg(">>> geonetworking_layer::start_pass_beaconing", p_beacon);
const LibItsGeoNetworking__TypesAndValues::LongPosVector& lpv = p_beacon.srcPosVector();
if (!_pass_beacon_table.has_entry(lpv.gnAddr().mid())) {
_pass_beacon_table.add_entry(lpv);
} // TODO Refined adding a boolean return code
} // End of start_pass_beaconing method
void geonetworking_layer::stop_pass_beaconing() {
loggers::get_instance().log(">>> geonetworking_layer::stop_pass_beaconing");
_pass_beacon_table.reset();
} // End of stop_pass_beaconing method
int geonetworking_layer::enable_secured_mode(const std::string& p_certificate_id, const boolean p_enforce_security) {
loggers::get_instance().log(">>> geonetworking_layer::enable_secured_mode: '%s' - %x", p_certificate_id.c_str(), p_enforce_security);
loggers::get_instance().log("geonetworking_layer::enable_secured_mode: _secured_mode = %x", _secured_mode);
loggers::get_instance().log("geonetworking_layer::enable_secured_mode: Setup secured mode");
_secured_mode = true;
setup_secured_mode();
}
_enable_security_checks = p_enforce_security;
params::const_iterator it = _params.find(params::certificate);
if (it == _params.cend()) {
_params.insert(std::pair<std::string, std::string>(std::string("certificate"), p_certificate_id));
} else {
loggers::get_instance().log("geonetworking_layer::enable_secured_mode: Certificate to be used: '%s'", _params[params::certificate].c_str());
int geonetworking_layer::disable_secured_mode() {
loggers::get_instance().log(">>> geonetworking_layer::disable_secured_mode");
_secured_mode = false;
_enable_security_checks = false;
return 0;
}
const LongPosVector* geonetworking_layer::get_lpv(const GN__Address& p_gn_address)
loggers::get_instance().log_msg(">>> geonetworking_layer::get_lpv", p_gn_address);
const LongPosVector* lpv = nullptr;
if (_location_table.has_entry(p_gn_address.mid())) {
lpv = _location_table.get_entry(p_gn_address.mid());
}
return lpv;
} // End of get_lpv
const LibItsGeoNetworking__TypesAndValues::BasicHeader geonetworking_layer::fill_basic_header() const {
return LibItsGeoNetworking__TypesAndValues::BasicHeader(
1, // GeoNetworking version
BasicNextHeader(
BasicNextHeader::e__commonHeader
),
0,
Lifetime(
4,
LtBase(LtBase::e__50ms)
),
1
);
}
void geonetworking_layer::fill_beacon(const OCTETSTRING& p_ll_address, const INTEGER p_station_type, const INTEGER p_country, const INTEGER type_of_address)
{
_beacon = new GeoNetworkingPdu();
HeaderTST h;
h.beaconHdr() = BeaconHeaderType(
HeaderType(HeaderType::e__beacon),
0
);
ExtendedHeader eh;
eh.beaconHeader() = BeaconHeader(
LongPosVector(
GN__Address(
TypeOfAddress((TypeOfAddress)type_of_address),
StationType((StationType)p_station_type),
p_country,
int2bit(0, 1),
0,
0
)
);
_beacon->basicHeader() = fill_basic_header();
_beacon->gnPacket().packet() = GnNonSecuredPacket(
CommonHeader(
NextHeader(
NextHeader::e__any
),
0,
h,
TrafficClass(
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("geonetworking_layer::fill_beacon: beacon value: ", *_beacon);
void geonetworking_layer::fill_gbc_packet(const OCTETSTRING& p_ll_address, const INTEGER& p_geoAreaPosLatitude, const INTEGER& p_geoAreaPosLongitude, const INTEGER& p_distanceA, const INTEGER& p_distanceB, const INTEGER& p_angle)
_gbc_packet = new GeoNetworkingPdu();
HeaderTST h;
h.geoBroadcastHdr() = GeoBroadcastHeaderType(
HeaderType(HeaderType::e__geoBroadcast),
HeaderSubTypeGeoBroadcast(HeaderSubTypeGeoBroadcast::e__geoBroadcastElip)
);
ExtendedHeader eh;
eh.geoBroadcastHeader() = GeoAnycastHeader( // GeoBradcastHeader is identical as GeoAnycastHeader
0,
0,
LongPosVector(
GN__Address(
TypeOfAddress(TypeOfAddress::e__manual), // TODO Use params
StationType(StationType::e__passengerCar), // TODO Use params
int2bit(1, 1), // PAI
0,
0
),
p_geoAreaPosLatitude,
p_geoAreaPosLongitude,
p_distanceA,
p_distanceB,
p_angle,
0
);
_gbc_packet->basicHeader() = fill_basic_header();
_gbc_packet->gnPacket().packet() = GnNonSecuredPacket(
CommonHeader(
NextHeader(
NextHeader::e__btpA
),
0,
h,
TrafficClass(
SCF(SCF::e__scfDisabled),
ChannelOffload(ChannelOffload::e__choffDisabled),
0
),
int2bit(128, 8), // Mobile stationnary flag set
0,
5,
0
),
OPTIONAL<ExtendedHeader>(eh),
OPTIONAL<GnRawPayload>()
);
_gbc_packet->gnPacket().packet().payload().set_to_omit();
_gbc_packet->gnPacket().securedMsg().set_to_omit();
//loggers::get_instance().log_msg("geonetworking_layer::fill_gbc_packet: packet value: ", *_gbc_packet);
} // End of fill_gbc_packet method
void geonetworking_layer::fill_shb_packet(const OCTETSTRING& p_ll_address)
{
_shb_packet = new GeoNetworkingPdu();
HeaderTST h;
h.tsbHdr() = TsbHeaderType(
HeaderType(HeaderType::e__topologicallyScopedBroadcast),
HeaderSubTypeTSB(HeaderSubTypeTSB::e__singleHop)
);
ExtendedHeader eh;
eh.shbHeader() = SHBHeader(
LongPosVector(
GN__Address(
TypeOfAddress(TypeOfAddress::e__manual), // TODO Use params
StationType(StationType::e__passengerCar), // TODO Use params
int2bit(1, 1), // PAI
0,
0
),
0
);
_shb_packet->basicHeader() = fill_basic_header();
_shb_packet->gnPacket().packet() = GnNonSecuredPacket(
CommonHeader(
NextHeader(
NextHeader::e__btpA
),
0,
h,
TrafficClass(
SCF(SCF::e__scfDisabled),
ChannelOffload(ChannelOffload::e__choffDisabled),
0
),
int2bit(128, 8), // Mobile stationnary flag set
0,
1,
0
),
OPTIONAL<ExtendedHeader>(eh),
OPTIONAL<GnRawPayload>()
);
_shb_packet->gnPacket().packet().payload().set_to_omit();
_shb_packet->gnPacket().securedMsg().set_to_omit();
//loggers::get_instance().log_msg("geonetworking_layer::fill_shb_packet: packet value: ", *_shb_packet);
} // End of fill_shb_packet method
void geonetworking_layer::fill_tsb_packet(const OCTETSTRING& p_ll_address, const int p_hop_number, const int p_max_hop_limit)
{
_tsb_packet = new GeoNetworkingPdu();
HeaderTST h;
h.tsbHdr() = TsbHeaderType(
HeaderType(HeaderType::e__topologicallyScopedBroadcast),
HeaderSubTypeTSB(HeaderSubTypeTSB::e__multiHop)
);
ExtendedHeader eh;
eh.tsbHeader() = TSBHeader(
0,
0,
LongPosVector(
GN__Address(
TypeOfAddress(TypeOfAddress::e__manual), // TODO Use params
StationType(StationType::e__passengerCar), // TODO Use params
_tsb_packet->basicHeader() = fill_basic_header();
_tsb_packet->gnPacket().packet() = GnNonSecuredPacket(
CommonHeader(
NextHeader(
NextHeader::e__btpA
),
0,
h,
TrafficClass(
SCF(SCF::e__scfDisabled),
ChannelOffload(ChannelOffload::e__choffDisabled),
0
),
int2bit(128, 8), // Mobile stationnary flag set
0,
p_max_hop_limit,
0
),
OPTIONAL<ExtendedHeader>(eh),
OPTIONAL<GnRawPayload>()
);
_tsb_packet->gnPacket().packet().payload().set_to_omit();
_tsb_packet->gnPacket().securedMsg().set_to_omit();
//loggers::get_instance().log_msg("geonetworking_layer::fill_tsb_packet: packet value: ", *_tsb_packet);
void geonetworking_layer::fill_ls_reply(const OCTETSTRING& p_ll_address)
{
_ls_reply = new GeoNetworkingPdu();
HeaderTST h;
h.lsHdr() = LsHeaderType(
HeaderType(HeaderType::e__locationService),
HeaderSubTypeLs(HeaderSubTypeLs::e__lsReply)
);
ExtendedHeader eh;
eh.lsReplyHeader() = LSReplyHeader(
0,
0,
LongPosVector(
GN__Address(
TypeOfAddress(TypeOfAddress::e__manual), // TODO Use params
StationType(StationType::e__passengerCar), // TODO Use params
int2bit(1, 1), // PAI
0,
0
),
ShortPosVector(
GN__Address(
TypeOfAddress(TypeOfAddress::e__manual), // TODO Use params
StationType(StationType::e__passengerCar), // TODO Use params
_ls_reply->basicHeader() = fill_basic_header();
_ls_reply->gnPacket().packet() = GnNonSecuredPacket(
CommonHeader(
NextHeader(
NextHeader::e__any
),
0,
h,
TrafficClass(
SCF(SCF::e__scfDisabled),
ChannelOffload(ChannelOffload::e__choffDisabled),
0
),
int2bit(128, 8), // Mobile stationnary flag set
0,
5,
0
),
OPTIONAL<ExtendedHeader>(eh),
OPTIONAL<GnRawPayload>()
);
_ls_reply->gnPacket().packet().payload().set_to_omit();
_ls_reply->gnPacket().securedMsg().set_to_omit();
//loggers::get_instance().log_msg("geonetworking_layer::fill_ls_reply: packet value: ", *_ls_reply);
void geonetworking_layer::timer_irq_sigalrm_handler(int p_signal, siginfo_t *p_signal_info, void *p_uc) {
//loggers::get_instance().log(">>> geonetworking_layer::timer_irq_sigalrm_handler: Caught signal %d", p_signal);
static_cast<geonetworking_layer *>(p_signal_info->si_value.sival_ptr)->send_beacon();
} // End of method timer_irq_sigalrm_handler
int geonetworking_layer::build_geonetworking_pdu(OCTETSTRING& data, params& params) {
loggers::get_instance().log(">>> geonetworking_layer::build_geonetworking_pdu");
params::const_iterator it = params.find(params::next_header);
if (it != params.cend()) {
next_header = it->second.c_str();
}
std::string header_type;
if (it != params.cend()) {
header_type = it->second.c_str();
}
std::string header_sub_type;
if (it != params.cend()) {
header_sub_type = it->second.c_str();
}
loggers::get_instance().log("geonetworking_layer::build_geonetworking_pdu: %s, %s, %s", next_header.c_str(), header_type.c_str(), header_sub_type.c_str());
if (header_type.compare("tsb") == 0) {
if (header_sub_type.compare("sh") == 0) { // Use SHB
ExtendedHeader* eh = static_cast<ExtendedHeader *>(_shb_packet->gnPacket().packet().extendedHeader().get_opt_value());
if (eh == nullptr) {
loggers::get_instance().error("geonetworking_layer::build_geonetworking_pdu: Wrong cast");
return -1;
}
// Update NextHeader
if (next_header.compare("btpB") == 0) {
_shb_packet->gnPacket().packet().commonHeader().nextHeader() = NextHeader::e__btpB;
} else { // Default btp is btpA
_shb_packet->gnPacket().packet().commonHeader().nextHeader() = NextHeader::e__btpA;
}
// Update payload
_shb_packet->gnPacket().packet().commonHeader().plLength() = data.lengthof();
_shb_packet->gnPacket().packet().payload() = OPTIONAL<OCTETSTRING>(data);
// Update timestamp
eh->shbHeader().srcPosVector().timestamp__().set_long_long_val(static_cast<unsigned int>(base_time::get_instance().get_its_current_time_mod_ms()));
loggers::get_instance().log_msg("geonetworking_layer::build_geonetworking_pdu: shb: ", *_shb_packet);
// Encode GeoNetworking PDU
OCTETSTRING os;
_codec.encode(*_shb_packet, os);
data = os;
} else { // Use TSB
ExtendedHeader* eh = static_cast<ExtendedHeader *>(_tsb_packet->gnPacket().packet().extendedHeader().get_opt_value());
if (eh == nullptr) {
loggers::get_instance().error("geonetworking_layer::build_geonetworking_pdu: Wrong cast");
return -1;
}
// Update sequence number
eh->tsbHeader().seqNumber() = _sequence_number++;
// Update NextHeader
if (next_header.compare("btpB") == 0) {
_tsb_packet->gnPacket().packet().commonHeader().nextHeader() = NextHeader::e__btpB;
} else { // Default btp is btpA
_tsb_packet->gnPacket().packet().commonHeader().nextHeader() = NextHeader::e__btpA;
}
// Update payload
_tsb_packet->gnPacket().packet().commonHeader().plLength() = data.lengthof();
_tsb_packet->gnPacket().packet().payload() = OPTIONAL<OCTETSTRING>(data);
// Update timestamp
eh->tsbHeader().srcPosVector().timestamp__().set_long_long_val(static_cast<unsigned int>(base_time::get_instance().get_its_current_time_mod_ms()));
loggers::get_instance().log_msg("geonetworking_layer::build_geonetworking_pdu: tsb: ", *_tsb_packet);
// Encode GeoNetworking PDU
OCTETSTRING os;
_codec.encode(*_tsb_packet, os);
data = os;
}
} else { // TODO To be continued
// Default: Use GBC
ExtendedHeader* eh = static_cast<ExtendedHeader *>(_gbc_packet->gnPacket().packet().extendedHeader().get_opt_value());
loggers::get_instance().error("geonetworking_layer::build_geonetworking_pdu: Wrong cast");
return -1;
}
// Update NextHeader
if (next_header.compare("btpB") == 0) {
_gbc_packet->gnPacket().packet().commonHeader().nextHeader() = NextHeader::e__btpB;
} else { // Default btp is btpA
_gbc_packet->gnPacket().packet().commonHeader().nextHeader() = NextHeader::e__btpA;
}
// Update sequence number
eh->geoBroadcastHeader().seqNumber() = _sequence_number++;
// Update payload
_gbc_packet->gnPacket().packet().commonHeader().plLength() = data.lengthof();
_gbc_packet->gnPacket().packet().payload() = OPTIONAL<OCTETSTRING>(data);
// Update timestamp
eh->geoBroadcastHeader().srcPosVector().timestamp__().set_long_long_val(static_cast<unsigned int>(base_time::get_instance().get_its_current_time_mod_ms()));
loggers::get_instance().log_msg("geonetworking_layer::build_geonetworking_pdu: gbc: ", *_gbc_packet);
// Encode GeoNetworking PDU
OCTETSTRING os;
_codec.encode(*_gbc_packet, os);
data = os;
}
return 0;
}
int geonetworking_layer::build_secured_pdu(OCTETSTRING& data, params& params) {
loggers::get_instance().log_msg(">>> geonetworking_layer::build_secured_pdu: ", data);
LibItsGeoNetworking__TypesAndValues::BasicHeader basic_header;
decode_basic_header(data, basic_header);
if (basic_header.nextHeader() == BasicNextHeader::e__securedPacket) { // Already secured (ATS Security test suite/f_sendSecuredGn/Cam/Denm TTCN-3 functions
// Leave data unchanged
loggers::get_instance().log_msg("<<< geonetworking_layer::build_secured_pdu: Leave data unchanged: ", data);
return 0;
}
unsigned int basic_header_len = 4;// FIXME How to retrive the BasicHeader length basic_header.get_descriptor()->raw->fieldlength / 8;
loggers::get_instance().log("geonetworking_layer::build_secured_pdu: basic_header_len = %d", basic_header_len);
basic_header.nextHeader() = BasicNextHeader::e__securedPacket;
OCTETSTRING unsecured_gn_payload = OCTETSTRING(data.lengthof() - basic_header_len, static_cast<const unsigned char*>(data) + basic_header_len);
if (security_services::get_instance().secure_gn_payload(unsecured_gn_payload, secured_gn_payload, params) != 0) {
loggers::get_instance().warning("geonetworking_layer::build_secured_pdu: failed to build secured pdu");
//loggers::get_instance().log_msg("geonetworking_layer::build_secured_pdu: New basic_header = ", basic_header);
RAW_enc_tr_pos rp;
rp.level=0;
rp.pos=NULL;