Commit fe15bc8d authored by garciay's avatar garciay
Browse files

Layers ongoing

parent b975074a
......@@ -10,11 +10,14 @@ class BITSTRING;
template<typename TPDUEnc, typename TPDUDec> class Codec
{
protected:
Params* _params;
public:
Codec() { loggers::get_instance().log("Codec::Codec"); };
Codec() : _params(NULL) { loggers::get_instance().log("Codec::Codec"); };
virtual ~Codec() { loggers::get_instance().log("Codec::~Codec"); };
virtual int encode(const TPDUEnc& msg, OCTETSTRING& data) = 0;
virtual int decode(const OCTETSTRING& data, TPDUDec& msg, Params* param = NULL) = 0;
virtual int decode(const OCTETSTRING& data, TPDUDec& msg, Params* params = NULL) = 0;
};
template<typename TPDU> class PERCodec
......
......@@ -10,15 +10,22 @@ public:
static const std::string& ssp;
static const std::string& its_aid;
static const std::string& gn_payload;
static const std::string& gn_next_header;
static const std::string& gn_header_type;
static const std::string& gn_header_sub_type;
static const std::string& gn_lifetime;
static const std::string& gn_traffic_class;
static const std::string& btp_type;
static const std::string& btp_payload;
static const std::vector<unsigned char>& mac_address;
static const std::string& btp_destination_port;
static const std::string& btp_info;
Params() : std::map<std::string, std::string>() {};
Params(const Params& p_params) : std::map<std::string, std::string>(p_params.begin(), p_params.end()) {};
virtual ~Params() {};
void log();
void reset();
static void convert(Params& p_param, const std::string p_parameters);
};
......@@ -9,35 +9,48 @@ const std::string& Params::mac_dst = std::string("mac_dst");
const std::string& Params::its_aid = std::string("its_aid");
const std::string& Params::ssp = std::string("ssp");
const std::string& Params::gn_payload = std::string("gn_payload");
const std::string& Params::gn_next_header = std::string("gnNextHeader");
const std::string& Params::gn_header_type = std::string("gnHeaderType");
const std::string& Params::gn_header_sub_type = std::string("gnHeaderSubtype");
const std::string& Params::gn_lifetime = std::string("gnLifetime");
const std::string& Params::gn_traffic_class = std::string("gnTrafficClass");
const std::string& Params::btp_type = std::string("btp_type");
const std::string& Params::btp_payload = std::string("btp_payload");
const std::vector<unsigned char>& Params::mac_address({0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF});
const std::string& Params::btp_destination_port = std::string("btpDestinationPort");
const std::string& Params::btp_info = std::string("btpInfo");
void Params::convert(Params& p_param, const std::string p_parameters) {
//loggers::get_instance().log(">>> Params::convert: '%s'", p_parameters.c_str());
// Sanity checks
if (p_parameters.length() == 0) {
return;
}
// Extract parameters
try {
std::regex rgx ("(\\w+)=(.*?)(,|$)");
std::sregex_iterator begin(p_parameters.cbegin(), p_parameters.cend(), rgx);
std::sregex_iterator end = std::sregex_iterator();
for (std::sregex_iterator it = begin; it != end; ++it) {
std::smatch m = *it;
//loggers::get_instance().log("Params::convert: %d - %s - %s - %s - %s", m.size(), m[0].str().c_str(), m[1].str().c_str(), m[2].str().c_str(), m[3].str().c_str());
p_param.insert(std::pair<std::string, std::string>(m[1].str(), m[2].str()));
} // End of 'for' statement
}
catch(const std::logic_error& e){
p_param.clear();
}
//loggers::get_instance().log(">>> Params::convert: '%s'", p_parameters.c_str());
// Sanity checks
if (p_parameters.length() == 0) {
return;
}
// Extract parameters
try {
std::regex rgx ("(\\w+)=(.*?)(,|$)");
std::sregex_iterator begin(p_parameters.cbegin(), p_parameters.cend(), rgx);
std::sregex_iterator end = std::sregex_iterator();
for (std::sregex_iterator it = begin; it != end; ++it) {
std::smatch m = *it;
//loggers::get_instance().log("Params::convert: %d - %s - %s - %s - %s", m.size(), m[0].str().c_str(), m[1].str().c_str(), m[2].str().c_str(), m[3].str().c_str());
p_param.insert(std::pair<std::string, std::string>(m[1].str(), m[2].str()));
} // End of 'for' statement
}
catch(const std::logic_error& e){
p_param.clear();
}
}
void Params::log() {
loggers::get_instance().log("Params::log");
for (const_iterator it = cbegin(); it != cend(); ++it) {
loggers::get_instance().log("\t(%s, %s)", it->first.c_str(), it->second.c_str());
} // End of 'for' statement
loggers::get_instance().log("Params::log");
for (const_iterator it = cbegin(); it != cend(); ++it) {
loggers::get_instance().log("\t(%s, %s)", it->first.c_str(), it->second.c_str());
} // End of 'for' statement
}
void Params::reset() {
loggers::get_instance().log("Params::reset");
for (iterator it = begin(); it != end(); ++it) {
it->second.clear();
} // End of 'for' statement
}
......@@ -63,11 +63,11 @@ int BTPCodec::encode_ (const Base_Type& type, const TTCN_Typedescriptor_t& field
return 0;
}
int BTPCodec::decode (const OCTETSTRING& data, LibItsBtp__TypesAndValues::BtpPacket& msg, Params* param)
int BTPCodec::decode (const OCTETSTRING& data, LibItsBtp__TypesAndValues::BtpPacket& msg, Params* params)
{
TTCN_EncDec::clear_error();
TTCN_Buffer decoding_buffer(data);
_param = param;
_params = params;
loggers::get_instance().log_to_hexa(">>> BTPCodec::decode: decoding_buffer=", decoding_buffer);
decode_(msg, LibItsBtp__TypesAndValues::BtpPacket_descr_, decoding_buffer);
......@@ -112,8 +112,17 @@ int BTPCodec::decode_ (Base_Type& type, const TTCN_Typedescriptor_t& field_descr
LibItsBtp__TypesAndValues::BtpHeader& b = static_cast<LibItsBtp__TypesAndValues::BtpHeader&>(type);
if (_type == BTPCodec::btpA) {
decode_(b.btpAHeader(), *b.btpAHeader().get_descriptor(), decoding_buffer);
if (_params != NULL) {
(*_params)[Params::btp_type] = std::string("btpA");
(*_params)[Params::btp_destination_port] = static_cast<int>(b.btpAHeader().destinationPort());
}
} else if (_type == BTPCodec::btpB) {
decode_(b.btpBHeader(), *b.btpBHeader().get_descriptor(), decoding_buffer);
if (_params != NULL) {
(*_params)[Params::btp_type] = std::string("btpB");
(*_params)[Params::btp_destination_port] = static_cast<int>(b.btpBHeader().destinationPort());
(*_params)[Params::btp_info] = static_cast<int>(b.btpBHeader().destinationPortInfo());
}
} else {
loggers::get_instance().error("BTPCodec::decode_: Invalid BTP type"); // Cannot be reached
}
......@@ -124,8 +133,8 @@ int BTPCodec::decode_ (Base_Type& type, const TTCN_Typedescriptor_t& field_descr
// Decode BtpRawPayload data structure
OCTETSTRING os(decoding_buffer.get_len() - decoding_buffer.get_pos(), decoding_buffer.get_data() + decoding_buffer.get_pos());
loggers::get_instance().log_msg("BTPCodec::decode_: s=", os);
if (_param != NULL) {
(*_param)[Params::btp_payload] = std::string(static_cast<const char *>(oct2str(os)));
if (_params != NULL) {
(*_params)[Params::btp_payload] = std::string(static_cast<const char *>(oct2str(os)));
}
dynamic_cast<OCTETSTRING &>(type) = os;
} else {
......
......@@ -34,7 +34,7 @@ void BTPLayer::receiveData(OCTETSTRING& data, Params& params)
_codec.decode(data, p.msgIn(), &params);
// Pass the BTP raw payload to the upper layers if any
std::map<std::string, std::string>::const_iterator it = params.find(Params::btp_payload);
Params::const_iterator it = params.find(Params::btp_payload);
if (it != params.cend()) {
loggers::get_instance().log("BTPLayer::receiveData: btp_payload=%s", it->second.c_str());
OCTETSTRING os(str2oct(CHARSTRING(it->second.c_str())));
......
......@@ -21,10 +21,9 @@ public:
class CAMCodec : public Codec<CAM__PDU__Descriptions::CAM, CAM__PDU__Descriptions::CAM>
{
CAMPDUCodec asnCodec;
Params* _params;
public:
CAMCodec() : Codec<CAM__PDU__Descriptions::CAM, CAM__PDU__Descriptions::CAM>(), asnCodec(), _params(NULL) { loggers::get_instance().log("CAMCodec::CAMCodec(D)"); };
CAMCodec() : Codec<CAM__PDU__Descriptions::CAM, CAM__PDU__Descriptions::CAM>(), asnCodec() { loggers::get_instance().log("CAMCodec::CAMCodec(D)"); };
virtual ~CAMCodec() { loggers::get_instance().log("CAMCodec::~CAMCodec"); };
virtual int encode (const CAM__PDU__Descriptions::CAM& cam, OCTETSTRING& data);
......
......@@ -5,6 +5,10 @@ EthernetLayer::EthernetLayer(const std::string & p_type, const std::string & par
loggers::get_instance().log(">>> EthernetLayer::EthernetLayer: %s, %s", to_string().c_str(), param.c_str());
// Setup parameters
Params::convert(_params, param);
Params::const_iterator it = _params.find("mac_bc");
if (it == _params.cend()) {
_params.insert(std::pair<std::string, std::string>(std::string("mac_bc"), "FFFFFFFFFFFF"));
}
//_params.log();
}
......@@ -12,19 +16,19 @@ void EthernetLayer::sendData(OCTETSTRING& data, Params& params) {
loggers::get_instance().log_msg(">>> EthernetLayer::sendData: ", data);
OCTETSTRING eth;
std::map<std::string, std::string>::const_iterator it = params.find(Params::mac_dst);
Params::const_iterator it = params.find(Params::mac_dst); // Find in provided parameters
if (it != params.cend()) {
eth = str2oct(CHARSTRING(it->second.c_str()));
} else {
eth = OCTETSTRING(Params::mac_address.size(), Params::mac_address.data());
eth = str2oct(CHARSTRING(_params["mac_bc"].c_str()));
}
it = params.find(Params::mac_src);
if (it != params.cend()) {
it = _params.find(Params::mac_src); // Find in layer parameters
if (it != _params.cend()) {
eth += str2oct(CHARSTRING(it->second.c_str()));
} else {
eth += OCTETSTRING(Params::mac_address.size(), Params::mac_address.data());
eth += str2oct(CHARSTRING(_params["mac_bc"].c_str()));
}
it = params.find("eth_type");
it = _params.find("eth_type"); // Find in layer parameters
if (it != params.cend()) {
eth += str2oct(CHARSTRING(it->second.c_str()));
} else {
......
......@@ -101,14 +101,22 @@ int GeoNetworkingCodec::encode_ (const Base_Type& type, const TTCN_Typedescripto
return 0;
}
int GeoNetworkingCodec::decode (const OCTETSTRING& data, LibItsGeoNetworking__TypesAndValues::GeoNetworkingPdu& msg, Params* param)
int GeoNetworkingCodec::decode (const OCTETSTRING& data, LibItsGeoNetworking__TypesAndValues::GeoNetworkingPdu& msg, Params* params)
{
TTCN_EncDec::clear_error();
TTCN_Buffer decoding_buffer(data);
_param = param;
_params = params;
loggers::get_instance().log_to_hexa(">>> GeoNetworkingCodec::decode: decoding_buffer=", decoding_buffer);
decode_(msg, LibItsGeoNetworking__TypesAndValues::GeoNetworkingPdu_descr_, decoding_buffer);
// Set layer parameters
if (_params != NULL) {
(*_params)[Params::gn_next_header] = _dc.next_header;
(*_params)[Params::gn_header_type] = _dc.header_type;
(*_params)[Params::gn_header_sub_type] = _dc.header_sub_type;
(*_params)[Params::gn_lifetime] = _dc.lifetime;
(*_params)[Params::gn_payload] = _dc.payload;
}
loggers::get_instance().log_msg("<<< GeoNetworkingCodec::decode: ", (const Base_Type&)msg);
return 0;
}
......@@ -126,6 +134,9 @@ int GeoNetworkingCodec::decode_ (Base_Type& type, const TTCN_Typedescriptor_t& f
return -1;
}
} // End of 'for' statement
if (std::string(r.get_descriptor()->name).compare("@LibItsGeoNetworking_TypesAndValues.Lifetime") == 0) {
_dc.lifetime = 0; // TODO
}
} else if (std::string(type.get_descriptor()->name).compare("@LibItsSecurity_TypesAndValues.SecuredMessage") == 0) {
dynamic_cast<OPTIONAL<LibItsSecurity__TypesAndValues::SecuredMessage> &>(type).set_to_omit();
} else {
......@@ -171,20 +182,22 @@ int GeoNetworkingCodec::decode_ (Base_Type& type, const TTCN_Typedescriptor_t& f
return -1;
}
// Align the payload length with the specified plLenght value
OCTETSTRING os;
if (_dc.plLength != 0) {
if ((unsigned char)s.lengthof() <= _dc.plLength) {
_dc.payload.assign(p, p + s.lengthof());
os = OCTETSTRING(s.lengthof(), p);
_dc.payload = std::string(static_cast<const char *>(oct2str(os)));
//_dc.payload.assign(p, p + s.lengthof());
} else {
_dc.payload.assign(p, p + _dc.plLength);
os = OCTETSTRING(_dc.plLength, p);
_dc.payload = std::string(static_cast<const char *>(oct2str(os)));
//_dc.payload.assign(p, p + _dc.plLength);
}
} else {
os = s;
_dc.payload.clear();
}
loggers::get_instance().log("GeoNetworkingCodec::decode_: vector length=%d", _dc.payload.size());
OCTETSTRING os(_dc.payload.size(), static_cast<const unsigned char *>(_dc.payload.data()));
if (_param != NULL) {
(*_param)[Params::gn_payload] = std::string(static_cast<const char *>(oct2str(os)));
}
loggers::get_instance().log("GeoNetworkingCodec::decode_: Payload: '%s'", _dc.payload.c_str());
dynamic_cast<OCTETSTRING &>(type) = os;
} else if (std::string(field_descriptor.name).compare("@LibItsGeoNetworking_TypesAndValues.CommonHeader.plLength") == 0) {
// Decode plLength data structure
......
#ifndef GNCODEC_H
#define GNCODEC_H
#include <vector>
#include "Codec.hh"
#include "Params.hh"
#include "loggers.hh" // TODO To be removed
......@@ -36,10 +34,11 @@ struct Decoding_Context {
unsigned char next_header;
unsigned char header_type;
unsigned char header_sub_type;
unsigned int lifetime;
unsigned int plLength;
std::vector<unsigned char> payload;
std::string payload;
Decoding_Context() : payload{} { next_header = 0xff; header_type = 0xff; header_sub_type = 0xff; plLength = -1; }
Decoding_Context() : payload() { next_header = 0xff; header_type = 0xff; header_sub_type = 0xff; lifetime = 0; plLength = -1; }
};
//typedef struct Decoding_Context Decoding_Context;
......@@ -48,8 +47,6 @@ class GeoNetworkingCodec : public Codec<LibItsGeoNetworking__TypesAndValues::Geo
Encoding_Context _ec;
Decoding_Context _dc;
Params* _param;
int encode_ (const Base_Type& type, const TTCN_Typedescriptor_t& field_descriptor, TTCN_Buffer& encoding_buffer);
int encode_extendedHeader(const LibItsGeoNetworking__TypesAndValues::ExtendedHeader& u, TTCN_Buffer& encoding_buffer);
int encode_decodedPayload(const LibItsGeoNetworking__TypesAndValues::DecodedPayload& u, TTCN_Buffer& encoding_buffer);
......@@ -59,11 +56,11 @@ class GeoNetworkingCodec : public Codec<LibItsGeoNetworking__TypesAndValues::Geo
int decode_extendedHeader(LibItsGeoNetworking__TypesAndValues::ExtendedHeader& u, TTCN_Buffer& decodin_buffer);
public:
GeoNetworkingCodec() : Codec<LibItsGeoNetworking__TypesAndValues::GeoNetworkingPdu, LibItsGeoNetworking__TypesAndValues::GeoNetworkingPdu>(), _ec(), _dc(), _param(NULL) { loggers::get_instance().log("GeoNetworkingCodec::GeoNetworkingCodec(D) :%d ", _ec.next_header); };
GeoNetworkingCodec() : Codec<LibItsGeoNetworking__TypesAndValues::GeoNetworkingPdu, LibItsGeoNetworking__TypesAndValues::GeoNetworkingPdu>(), _ec(), _dc() { loggers::get_instance().log("GeoNetworkingCodec::GeoNetworkingCodec(D) :%d ", _ec.next_header); };
virtual ~GeoNetworkingCodec() { loggers::get_instance().log("GeoNetworkingCodec::~GeoNetworkingCodec"); };
virtual int encode (const LibItsGeoNetworking__TypesAndValues::GeoNetworkingPdu& msg, OCTETSTRING& data);
virtual int decode (const OCTETSTRING& data, LibItsGeoNetworking__TypesAndValues::GeoNetworkingPdu& msg, Params* param = NULL);
virtual int decode (const OCTETSTRING& data, LibItsGeoNetworking__TypesAndValues::GeoNetworkingPdu& msg, Params* params = NULL);
};
#endif
......@@ -3,23 +3,31 @@
#include "loggers.hh"
GeoNetworkingLayer::GeoNetworkingLayer(const std::string & p_type, const std::string & param) : TLayer<LibItsGeoNetworking__TestSystem::GeoNetworkingPort>(p_type), _params(), _codec() {
GeoNetworkingLayer::GeoNetworkingLayer(const std::string & p_type, const std::string & param) : TLayer<LibItsGeoNetworking__TestSystem::GeoNetworkingPort>(p_type), _params(), _codec(), _thread(NULL), _running(FALSE) {
loggers::get_instance().log(">>> GeoNetworkingLayer::GeoNetworkingLayer: %s, %s", to_string().c_str(), param.c_str());
// Setup parameters
Params::convert(_params, param);
Params::const_iterator it = _params.find("mac_bc");
if (it == _params.cend()) {
_params.insert(std::pair<std::string, std::string>(std::string("mac_bc"), "FFFFFFFFFFFF"));
}
}
void GeoNetworkingLayer::sendMsg(const LibItsGeoNetworking__TestSystem::GeoNetworkingReq& p, const Params& params) {
GeoNetworkingLayer::~GeoNetworkingLayer() {
if (_thread != NULL) {
_running = FALSE;
// Wait for the working thread to terminate
_thread->join();
loggers::get_instance().log("GeoNetworkingLayer::~GeoNetworkingLayer: Thread were stops");
}
}
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);
// Update parameters
Params par(params); // FIXME Review all const Param& in method declarations
par.insert(std::pair<std::string, std::string>(Params::mac_dst, std::string(static_cast<const char *>(oct2str(p.macDestinationAddress())))));
par.insert(std::pair<std::string, std::string>(Params::its_aid, std::string(static_cast<const char *>(int2str(p.its__aid())))));
sendData(data, par);
sendData(data, params);
}
void GeoNetworkingLayer::sendData(OCTETSTRING& data, Params& params) {
......@@ -35,12 +43,12 @@ void GeoNetworkingLayer::receiveData(OCTETSTRING& data, Params& params) {
_codec.decode(data, p.msgIn(), &params);
// Add lower layers parameters
// 1. Destination MAC address
std::map<std::string, std::string>::const_iterator it = params.find(Params::mac_dst);
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() = OCTETSTRING(Params::mac_address.size(), Params::mac_address.data());
p.macDestinationAddress() = str2oct(CHARSTRING(_params["mac_bc"].c_str()));
}
// 2. ssp
it = params.find(Params::ssp);
......@@ -72,6 +80,22 @@ void GeoNetworkingLayer::receiveData(OCTETSTRING& data, Params& params) {
toAllUpperPorts(p, params);
}
void GeoNetworkingLayer::start_beconning() {
loggers::get_instance().log(">>> GeoNetworkingLayer::start_beaconing");
}
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;
}
}
class GeoNetworkingFactory: public LayerFactory {
static GeoNetworkingFactory _f;
public:
......
#ifndef GEONETWORKING_LAYER_H
#define GEONETWORKING_LAYER_H
#include <thread>
#include <mutex>
#include "Layer.hh"
#include "GeoNetworkingCodec.hh"
......@@ -13,15 +16,20 @@ namespace LibItsGeoNetworking__TestSystem {
class GeoNetworkingLayer : public TLayer<LibItsGeoNetworking__TestSystem::GeoNetworkingPort> {
Params _params;
GeoNetworkingCodec _codec;
std::thread * _thread;
bool _running;
public:
GeoNetworkingLayer() : TLayer<LibItsGeoNetworking__TestSystem::GeoNetworkingPort>(), _params(), _codec() {};
GeoNetworkingLayer(const std::string & p_type, const std::string & param);
virtual ~GeoNetworkingLayer() {};
virtual ~GeoNetworkingLayer();
void sendMsg(const LibItsGeoNetworking__TestSystem::GeoNetworkingReq&, const Params& param);
void sendMsg(const LibItsGeoNetworking__TestSystem::GeoNetworkingReq&, Params& param);
virtual void sendData(OCTETSTRING& data, Params& params);
virtual void receiveData(OCTETSTRING& data, Params& params);
void start_beconning();
void stop_beaconing();
};
#endif
......@@ -9,7 +9,7 @@
#include "PcapLayer.hh"
#include "loggers.hh"
PcapLayer::PcapLayer(const std::string & p_type, const std::string & param) : Layer(p_type), PORT(p_type.c_str()), _params(), _device(NULL), _pcap_h(-1), _thread(NULL), _running(FALSE), _resume(), _time_key("PcapLayer::Handle_Fd_Event_Readable") {
PcapLayer::PcapLayer(const std::string & p_type, const std::string & param) : Layer(p_type), PORT(p_type.c_str()), _params(), _device(NULL), _pcap_h(-1), _thread(NULL), _running(FALSE), _resume(), _sent_file(NULL), _time_key("PcapLayer::Handle_Fd_Event_Readable") {
loggers::get_instance().log(">>> PcapLayer::PcapLayer: %s, %s", to_string().c_str(), param.c_str());
_fd[0] = -1; _fd[1] = -1;
// Setup parameters
......@@ -17,7 +17,7 @@ PcapLayer::PcapLayer(const std::string & p_type, const std::string & param) : La
//_params.log();
// Prepare capture processing
char error_buffer[PCAP_ERRBUF_SIZE];
std::map<std::string, std::string>::const_iterator it = _params.find(std::string("nic"));
Params::const_iterator it = _params.find(std::string("nic"));
if ((it != _params.end()) && !it->second.empty()) { // Use online capture
// Fetch the network address and network mask
/*bpf_u_int32 mask; // subnet mask
......@@ -43,7 +43,7 @@ PcapLayer::PcapLayer(const std::string & p_type, const std::string & param) : La
} else {
// Check file name
it = _params.find(std::string("file"));
if ((it != _params.end()) && !it->second.empty()) { // Use offline capture
if ((it != _params.cend()) && !it->second.empty()) { // Use offline capture
struct stat s = {0};
if ((stat(_params["file"].c_str(), &s) != 0) || !S_ISREG(s.st_mode)) {
loggers::get_instance().error("PcapLayer::PcapLayer: Failed to acces PCAP file %s", _params["file"].c_str());
......@@ -53,7 +53,20 @@ PcapLayer::PcapLayer(const std::string & p_type, const std::string & param) : La
if (_device == NULL) {
loggers::get_instance().error("PcapLayer::PcapLayer: Failed to open PCAP file %s", error_buffer);
} // else, continue
// Create the dump file for the sent packet based on the openned file name and the current time in milliseconds
it = _params.find("save_mode");
if ((it != _params.cend()) && (it->second.compare("1") == 0)) {
unsigned long ms = std::chrono::system_clock::now().time_since_epoch() / std::chrono::milliseconds(1);
std::string ext("_" + std::to_string(ms));
int i = _params["file"].find(".pcap");
if (i > 0) {
std::string f(_params["file"].substr(0, i) + ext + ".pcap");
loggers::get_instance().log("PcapLayer::PcapLayer: Save file name: %s", f.c_str());
if ((_sent_file = pcap_dump_open(_device, f.c_str())) == NULL) {
loggers::get_instance().warning("PcapLayer::PcapLayer: Failed to open save file %s", f.c_str());
}
}
} // else, nothing to do
} else {
loggers::get_instance().error("PcapLayer::PcapLayer: Failed to open PCAP file %s", error_buffer);
}
......@@ -76,9 +89,9 @@ PcapLayer::PcapLayer(const std::string & p_type, const std::string & param) : La
pcap_freecode(&f);
}
// Pass the device file handler to the polling procedure
if (_pcap_h != -1) {
if (_pcap_h != -1) { // Live capture
Handler_Add_Fd_Read(_pcap_h);
} else {
} else { // Offline capture
// Create a pipe
if (pipe2(_fd, O_NONBLOCK) == -1) {
loggers::get_instance().error("PcapLayer::PcapLayer: Failed to create a pipe: %s", ::strerror(errno));
......@@ -114,6 +127,9 @@ PcapLayer::~PcapLayer() {
close(_fd[0]);
close(_fd[1]);
}
if (_sent_file != NULL) {
pcap_dump_close(_sent_file);
}
pcap_close(_device);
}
} // End of dtor
......@@ -123,11 +139,27 @@ void * PcapLayer::run(void *p_this) {
// Pointer the main object
PcapLayer& p = *static_cast<PcapLayer *>(p_this);
// Set running flags
p._running = TRUE;
// Wait a little bit before to start sending packet
std::this_thread::sleep_for(std::chrono::seconds(1));
Params::const_iterator it = p._params.find("frame_offset");
if ((it != p._params.cend()) && (it->second.compare("0") != 0)) {
// TODO Try t use PCAP filter to start directly to the correct frame offset
/*try {
unsigned int offset = std::stoul(str_dec, &s);
// Skip frames
struct pcap_pkthdr *pkt_header;
const u_char *pkt_data;
int result = pcap_next_ex(_device, &pkt_header, &pkt_data);
if (result == 1) { // Succeed
}
}
catch (invalid_argument& i) {
}
catch (out_of_range& o) {
}*/
}
// Let's go
p._running = TRUE;
while (p._running) { // Loop while _running flag is up
if (p._resume.try_lock() == TRUE) { // Previous packet was consumed, lock for the next one
write(p._fd[1], "\n", 1);
......@@ -147,6 +179,15 @@ void PcapLayer::sendData(OCTETSTRING& data, Params& params) {
if (pcap_inject(_device, static_cast<const unsigned char *>(data), data.lengthof()) != 0) {
loggers::get_instance().error("PcapLayer::sendData: Failed to send packet: %s", pcap_geterr(_device));
}
} else if (_sent_file != NULL) {
struct pcap_pkthdr hdr;
std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
std::chrono::milliseconds ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch());
hdr.ts.tv_sec = ms.count() / 1000;
hdr.ts.tv_usec = (ms.count() % 1000) * 1000;
hdr.caplen = data.lengthof();
hdr.len = hdr.caplen;
pcap_dump((u_char *)_sent_file, &hdr, static_cast<const unsigned char *>(data));
} else {
loggers::get_instance().log("PcapLayer::sendData: Offline mode, operation was skipped");
// TODO Use PCAP dump file to store sent message in a file??
......@@ -180,8 +221,7 @@ void PcapLayer::Handle_Fd_Event_Readable(int fd) {
float duration;
loggers::get_instance().set_start_time(_time_key);
this->receiveData(os, params); // TODO Check execution time for decoding operation
loggers::get_instance().set_stop_time(_time_key, duration);
loggers::get_instance().set_stop_time(_time_key, duration);
}
} // else, skip the packet
// Specific to offline mode
......
......@@ -16,6 +16,7 @@ class PcapLayer : public Layer, public PORT {
std::thread * _thread;
bool _running;
std::mutex _resume;
pcap_dumper_t* _sent_file;
std::string _time_key;
int _fd[2];
......