#include #include "GeoNetworkingLayer.hh" #include "GeoNetworkingTypes.hh" #include "loggers.hh" using namespace LibItsGeoNetworking__TypesAndValues; GeoNetworkingLayer::GeoNetworkingLayer(const std::string & p_type, const std::string & param) : TLayer(p_type), _params(), _codec(), _beacon(NULL), _thread(NULL), _sendData(), _running(FALSE) { loggers::get_instance().log(">>> GeoNetworkingLayer::GeoNetworkingLayer: %s, %s", to_string().c_str(), param.c_str()); // Setup parameters Params::convert(_params, param); // 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("mac_bc"), "FFFFFFFFFFFF")); } // Prepare the static part of the TestSystem beacon // TODO Add a method _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, ll_address ), 0, latitude, 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(eh), OPTIONAL() ); _beacon->gnPacket().packet().payload().set_to_omit(); _beacon->gnPacket().securedMsg().set_to_omit(); // loggers::get_instance().log_msg("GeoNetworkingLayer::GeoNetworkingLayer: beacon value: ", *p._beacon); } GeoNetworkingLayer::~GeoNetworkingLayer() { stop_beaconing(); delete _beacon; } void GeoNetworkingLayer::sendMsg(const LibItsGeoNetworking__TestSystem::GeoNetworkingReq& p, Params& params) { loggers::get_instance().log(">>> GeoNetworkingLayer::sendMsg"); // Encode GeoNetworking PDU OCTETSTRING data; _codec.encode(p.msgOut(), data); sendData(data, 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 sendToAllLayers(data, params); _sendData.unlock(); loggers::get_instance().log("<<< GeoNetworkingLayer::sendData"); } void GeoNetworkingLayer::receiveData(OCTETSTRING& data, Params& params) { loggers::get_instance().log_msg(">>> GeoNetworkingLayer::receiveData: ", data); // Decode the payload LibItsGeoNetworking__TestSystem::GeoNetworkingInd p; _codec.decode(data, p.msgIn(), ¶ms); // Add lower layers parameters // 1. Destination MAC address Params::const_iterator it = params.find(Params::mac_dst); if (it != params.cend()) { loggers::get_instance().log("GeoNetworkingLayer::receiveData: dst=%s", it->second.c_str()); p.macDestinationAddress() = str2oct(CHARSTRING(it->second.c_str())); } else { p.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()); p.ssp() = str2bit(CHARSTRING(it->second.c_str())); } else { p.ssp().set_to_omit(); } // 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()); p.its__aid() = std::stoi(it->second.c_str()); } else { p.its__aid().set_to_omit(); } // 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 toAllUpperPorts(p, params); } void GeoNetworkingLayer::start_beaconing() { loggers::get_instance().log(">>> GeoNetworkingLayer::start_beaconing"); // Create the offline reader thread _thread = new std::thread(&GeoNetworkingLayer::run_beaconing, (void *)this); if (_thread == NULL) { loggers::get_instance().error("GeoNetworkingLayer::start_beaconing: Failed to start beaconing thread"); } // Wait for the thread while (_running == FALSE) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); } // Thread was started loggers::get_instance().log("<<< PcapLayer::PcapLayer"); } void GeoNetworkingLayer::stop_beaconing() { loggers::get_instance().log(">>> GeoNetworkingLayer::stop_beaconing"); if (_thread != NULL) { _running = FALSE; // Wait for the working thread to terminate _thread->join(); loggers::get_instance().log("GeoNetworkingLayer::stop_beaconing: Thread were stops"); _thread = NULL; } } void* GeoNetworkingLayer::run_beaconing(void* p_this) { loggers::get_instance().log(">>> GeoNetworkingLayer::run_beaconing"); // Pointer the main object GeoNetworkingLayer& p = *static_cast(p_this); Params params(p._params); std::chrono::milliseconds expiry(1000); // Default is set to 1 second Params::const_iterator it = params.find("TsBeaconInterval"); if (it != params.cend()) { expiry = std::chrono::milliseconds(std::stoul(it->second)); } ExtendedHeader* eh = static_cast(p._beacon->gnPacket().packet().extendedHeader().get_opt_value()); if (eh == NULL) { loggers::get_instance().error("GeoNetworkingLayer::run_beaconing: Wrong cast"); } GeoNetworkingCodec codec; // Start beaconing p._running = TRUE; std::this_thread::sleep_for(std::chrono::milliseconds(100)); while (p._running == TRUE) { // Loop while _running flag is up // Update timestamp unsigned long long ms = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count() - 1072911600000L; // TODO Add method such as its_tme() & its_time_mod() eh->beaconHeader().srcPosVector().timestamp__() = ms; // Encode message using TITAN because of payload in omited TTCN_Buffer encoding_buffer; p._beacon->encode(*(p._beacon->get_descriptor()), encoding_buffer, TTCN_EncDec::CT_RAW); OCTETSTRING data(encoding_buffer.get_len(), encoding_buffer.get_data()); // Send it p.sendData(data, params); // Timer ms = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count() + expiry.count(); while ((p._running == TRUE) && (ms > std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count())); } // End of 'while' statement< loggers::get_instance().log("<<< GeoNetworkingLayer::run_beaconing"); return NULL; } class GeoNetworkingFactory: public LayerFactory { static GeoNetworkingFactory _f; public: 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) { return new GeoNetworkingLayer(type, param); } GeoNetworkingFactory GeoNetworkingFactory::_f;