Loading ccsrc/Protocols/Pcap/pcap_cygwin_layer.cc 0 → 100755 +262 −0 Original line number Diff line number Diff line #if defined (__CYGWIN__) #define _GNU_SOURCE #include <unistd.h> #include <fcntl.h> #include <sys/stat.h> #include <errno.h> #include <chrono> #include <sstream> #include <iomanip> #include <Port.hh> #include "pcap_layer_factory.hh" #include "loggers.hh" #include <pcap.h> typedef struct { bpf_int32 tv_sec; /* seconds */ bpf_int32 tv_usec; /* microseconds */ }pcap_o_timeval; typedef struct pcap_o_pkthdr { pcap_o_timeval ts; /* time stamp */ bpf_u_int32 caplen; /* length of portion present */ bpf_u_int32 len; /* length this packet (off wire) */ }pcap_o_pkthdr; extern "C" int pcap_oid_get_request(pcap_t *p, bpf_u_int32 oid, void *data, size_t *lenp); static const char* _hexDigits = "0123456789ABCDEF"; static char * _bin2hex(char * hex, size_t hlen, const char * bin, size_t blen) { const unsigned char *b, *e; char * s; // sanity check if (hlen >= 0 && hlen < blen * 2) return NULL; b = (const unsigned char *)bin; e = b + blen - 1; s = hex + blen * 2; if (s < hex + hlen) *s = 0; for (; b <= e; e--){ *(--s) = _hexDigits[(*e) & 0xF]; *(--s) = _hexDigits[(*e) >> 4]; } return hex + blen * 2; } pcap_layer::pcap_layer(const std::string& p_type, const std::string& param) : layer(p_type), PORT(p_type.c_str()), _params(), _device(NULL), _running(FALSE), _time_key("pcap_layer::Handle_Fd_Event_Readable") { loggers::get_instance().log(">>> pcap_layer::pcap_layer: %s, %s", p_type.c_str(), param.c_str()); params::convert(_params, param); char error_buffer[PCAP_ERRBUF_SIZE]; params::const_iterator it; std::string nic; //network interface name bpf_u_int32 mask; // subnet mask bpf_u_int32 net; // ip address it = _params.find(params::nic); if ((it == _params.end()) || it->second.empty()) { loggers::get_instance().error("pcap_layer::pcap_layer: NIC must be specified"); return; } nic = std::string("\\Device\\NPF_{") + it->second + "}"; if (pcap_lookupnet(nic.c_str(), &net, &mask, error_buffer) != 0) { loggers::get_instance().error("pcap_layer::pcap_layer: pcap_layer::pcap_layer: Failed to fetch newtork address for device %s", nic.c_str()); } loggers::get_instance().log("pcap_layer::pcap_layer: Device %s Network address: %d", nic.c_str(), net); // Open the device _device = pcap_open_live(nic.c_str(), 65536, 1, 200, error_buffer); if (_device == NULL) { loggers::get_instance().error("pcap_layer::pcap_layer: Failed to open device %s", nic.c_str()); return; } // Setup filter std::string filter = ""; std::string mac_src; it = _params.find(params::mac_src); if (it != _params.end() && !it->second.empty()) { mac_src = it->second; } else { // Not found // determine it automatically #ifndef OID_802_3_CURRENT_ADDRESS #define OID_802_3_CURRENT_ADDRESS 0x01010102 #endif char mac[6] = {0}; size_t l = sizeof(mac); pcap_oid_get_request(_device, OID_802_3_CURRENT_ADDRESS, mac, &l); char buf[13]; *_bin2hex(buf, sizeof(buf), mac, 6) = 0; mac_src = buf; loggers::get_instance().user("pcap_layer::pcap_layer: local MAC is %s", mac_src.c_str()); } std::string mac_bc; it = _params.find(params::mac_bc); if (it != _params.end() && !it->second.empty()) mac_bc = it->second; else mac_bc = "ffffffffffff"; if(mac_bc == mac_src || mac_src.empty()) filter = "ether dst " + mac_bc; else filter = "( ether dst " + mac_bc + " or ether dst " + mac_src + " )"; if(! mac_src.empty()) // Reject ITS messages sent by this component filter += " and not ether src " + mac_src; // Add user defined filter it = _params.find(std::string("filter")); if ((it != _params.end()) && !it->second.empty()) { filter += std::string(" ") + it->second; } // Log final PCAP filter loggers::get_instance().user("pcap_layer::pcap_layer: Filter: %s", filter.c_str()); // setup filter { struct bpf_program f = {0}; if (pcap_compile(_device, &f, filter.c_str(), 1, PCAP_NETMASK_UNKNOWN) != 0) { loggers::get_instance().error("pcap_layer::pcap_layer: Failed to compile PCAP filter"); } else { if (pcap_setfilter(_device, &f) != 0) { loggers::get_instance().error("pcap_layer::pcap_layer: Failed to set PCAP filter"); } } pcap_freecode(&f); } _o_params.insert(std::pair<std::string, std::string>(std::string("timestamp"), std::string())); // create pipe and run thread if (pipe2(_fd, O_NONBLOCK) == -1) { loggers::get_instance().error("pcap_layer::pcap_layer: Failed to create a pipe: %s", ::strerror(errno)); } // Pass the pipe handler to the polling procedure loggers::get_instance().log("pcap_layer::pcap_layer: Call handler with descriptor %d", _fd[0]); Handler_Add_Fd_Read(_fd[0]); // Create the reader thread _thread = new std::thread(&pcap_layer::run, (void *)this); if (_thread == NULL) { loggers::get_instance().error("pcap_layer::pcap_layer: Failed to start offline thread"); } while (_running == FALSE) { std::this_thread::sleep_for(std::chrono::milliseconds(500)); } // Thread was started loggers::get_instance().log("<<< pcap_layer::pcap_layer"); } // End of ctor pcap_layer::~pcap_layer() { loggers::get_instance().log(">>> pcap_layer::~pcap_layer"); if (_device != NULL) { if (_thread != NULL) { _running = FALSE; // Wait for the working thread to terminate _thread->join(); loggers::get_instance().log("pcap_layer::~pcap_layer: Thread were stops"); // Cleanup delete _thread; close(_fd[0]); close(_fd[1]); } pcap_close(_device); } } // End of dtor void* pcap_layer::run(void* p_this) { pcap_layer& p = *static_cast<pcap_layer *>(p_this); return p.thread(); } void* pcap_layer::thread() { pcap_o_pkthdr *pkt_header; const u_char *pkt_data; unsigned char pkt_count = 0; loggers::get_instance().log(">>> pcap_layer::run"); _running = TRUE; // wait a bit before sending first packet std::this_thread::sleep_for(std::chrono::milliseconds(500)); while (_running) { // Loop while _running flag is up // get next frame int result = pcap_next_ex(_device, (struct pcap_pkthdr**)&pkt_header, &pkt_data); if(result == 0){ continue; } if(result < 0){ loggers::get_instance().log("<<< pcap_layer::run: error %s", pcap_geterr(_device)); break; } while(_running && !_resume.try_lock()) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); } #if 0 { char buf[128]; std::time_t t = pkt_header->ts.tv_sec; std::tm * pt = std::localtime( &t ); t = std::strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", pt); std::sprintf(buf+t, ".%06ld", pkt_header->ts.tv_usec); _o_params["timestamp"] = std::string(buf); } #else _o_params["timestamp"] = std::to_string(pkt_header->ts.tv_usec); #endif _o_data = OCTETSTRING(pkt_header->len, pkt_data); write(_fd[1], &pkt_count, 1);pkt_count++; } _running = FALSE; loggers::get_instance().log("<<< pcap_layer::run"); return NULL; } void pcap_layer::send_data(OCTETSTRING& data, params& params) { loggers::get_instance().log_msg(">>> pcap_layer::send_data: ", data); if (pcap_sendpacket(_device, static_cast<const unsigned char *>(data), data.lengthof()) == -1) { loggers::get_instance().error("pcap_layer::send_data: Failed to send packet: %s", pcap_geterr(_device)); } } void pcap_layer::receive_data(OCTETSTRING& data, params& params) { loggers::get_instance().log(">>> pcap_layer::receive_data: Received %d bytes", data.lengthof()); loggers::get_instance().log_to_hexa("Packet dump", data); // Pass the packet to the upper layers receive_to_all_layers(data, params); } void pcap_layer::Handle_Fd_Event_Readable(int fd) { char c[2]; float duration; loggers::get_instance().set_start_time(_time_key); this->receive_data(_o_data, _o_params); loggers::get_instance().set_stop_time(_time_key, duration); read(_fd[0], &c, 1); _resume.unlock(); } pcap_layer_factory pcap_layer_factory::_f; #endif //__CYGWIN__ ccsrc/Protocols/Pcap/pcap_cygwin_layer.hh 0 → 100755 +78 −0 Original line number Diff line number Diff line /*! * \file pcap_layer.hh * \brief Header file for ITS Offline Pcap port layer. * \author ETSI STF525 * \copyright ETSI Copyright Notification * No part may be reproduced except as authorized by written permission. * The copyright and the foregoing restriction extend to reproduction in all media. * All rights reserved. * \version 0.1 */ #pragma once #include <thread> #include <mutex> #include "t_layer.hh" #include "params.hh" #include <Octetstring.hh> class PORT; //! Forward declaration of TITAN class typedef struct pcap pcap_t; /*! * \class pcap_layer * \brief This class provides description of ITS PCAP port protocol layer */ class pcap_layer : public layer, public PORT { params _params; //! Layer parameters pcap_t* _device; //! Device handle std::thread* _thread; //! Thread handle, used to read PCAP file instead of NIC, used in file mode std::mutex _resume; bool _running; //! Set to true when the thread is running, used in file mode int _fd[2]; //! pipe to signal to Titan OCTETSTRING _o_data; params _o_params; std::string _time_key; static void* run(void* p_this); public: void* thread(void); public: //! \publicsection /*! * \brief Specialised constructor * Create a new instance of the pcap_layer class * \param[in] p_type \todo * \param[in] p_param \todo */ pcap_layer(const std::string& p_type, const std::string& param); /*! * \brief Default destructor */ virtual ~pcap_layer(); /*! * \virtual * \fn void send_data(OCTETSTRING& data, params& params); * \brief Send bytes formated data to the lower layers * \param[in] p_data The data to be sent * \param[in] p_params Some parameters to overwrite default value of the lower layers parameters */ virtual void send_data(OCTETSTRING& data, params& params); /*! * \virtual * \fn void receive_data(OCTETSTRING& data, params& params); * \brief Receive bytes formated data from the lower layers * \param[in] p_data The bytes formated data received * \param[in] p_params Some lower layers parameters values when data was received */ virtual void receive_data(OCTETSTRING& data, params& info); void Handle_Fd_Event_Readable(int fd); }; ccsrc/Protocols/Pcap/pcap_layer.cc +2 −50 Original line number Diff line number Diff line #if defined (__CYGWIN__) #define _GNU_SOURCE #endif #if 0 #include <unistd.h> #include <fcntl.h> #include <sys/stat.h> Loading @@ -11,27 +9,8 @@ #include "pcap_layer_factory.hh" #if defined (__CYGWIN__) typedef void* HANDLE; typedef unsigned int DWORD; extern "C" { DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds); HANDLE pcap_getevent(pcap_t *p); } typedef struct { bpf_int32 tv_sec; /* seconds */ bpf_int32 tv_usec; /* microseconds */ }pcap_o_timeval; typedef struct pcap_o_pkthdr { pcap_o_timeval ts; /* time stamp */ bpf_u_int32 caplen; /* length of portion present */ bpf_u_int32 len; /* length this packet (off wire) */ }pcap_o_pkthdr; #else typedef struct pcap_pkthdr pcap_o_pkthdr; typedef struct timeval pcap_o_timeval; #endif #include "loggers.hh" Loading @@ -51,11 +30,7 @@ pcap_layer::pcap_layer(const std::string& p_type, const std::string& param) : la bpf_u_int32 net; // ip address std::string nic; online = true; #ifdef __CYGWIN__ nic = std::string("\\Device\\NPF_{") + _params[params::nic] + "}"; #else nic = _params[params::nic]; #endif if (pcap_lookupnet(nic.c_str(), &net, &mask, error_buffer) != 0) { loggers::get_instance().error("pcap_layer::pcap_layer: pcap_layer::pcap_layer: Failed to fetch newtork address for device %s", nic.c_str()); } Loading @@ -69,13 +44,11 @@ pcap_layer::pcap_layer(const std::string& p_type, const std::string& param) : la if (pcap_setnonblock(_device, 1, error_buffer) != 0) { loggers::get_instance().error("pcap_layer::pcap_layer: Failed to set blocking mode: %s", error_buffer); } #if ! defined (__CYGWIN__) // Retrieve the device file handler _pcap_h = pcap_get_selectable_fd(_device); if (_pcap_h == -1) { loggers::get_instance().error("pcap_layer::pcap_layer: Failed to get device handler"); } #endif } else { // Check file name it = _params.find(std::string("file")); Loading Loading @@ -220,28 +193,6 @@ void* pcap_layer::thread() { catch (out_of_range& o) { }*/ } #if defined (__CYGWIN__) // check HANDLE emulation for pcap if(_fd[0] == _pcap_h) { HANDLE h = pcap_getevent(_device); _running = TRUE; while (_running) { // Loop while _running flag is up DWORD rc = WaitForSingleObject(h, 1000); if(rc == 0){ // event raised std::this_thread::sleep_for(std::chrono::milliseconds(1000)); if (_resume.try_lock() == TRUE) { // Previous packet was consumed, lock for the next one write(_fd[1], "\n", 1); // Any character will do the job } else { // not ready yet std::this_thread::sleep_for(std::chrono::milliseconds(100)); } }else if(rc == 0x00000102L) { // timeout }else { } } return NULL; } #endif // Let's go _running = TRUE; while (_running) { // Loop while _running flag is up Loading Loading @@ -322,3 +273,4 @@ void pcap_layer::Handle_Fd_Event_Readable(int fd) { pcap_layer_factory pcap_layer_factory::_f; #endif // !CYGWIN ccsrc/Protocols/Pcap/pcap_offline_layer.cc +4 −1 Original line number Diff line number Diff line Loading @@ -32,7 +32,7 @@ typedef struct timeval pcap_o_timeval; #endif pcap_offline_layer::pcap_offline_layer(const std::string& p_type, const std::string& param) : layer(p_type), PORT(p_type.c_str()), _params(), _device(NULL), _running(FALSE) { layer(p_type), PORT(p_type.c_str()), _params(), _device(NULL), _running(FALSE), _time_key("pcap_offline_layer::Handle_Fd_Event_Readable") { loggers::get_instance().log(">>> pcap_offline_layer::pcap_offline_layer: %s, %s", p_type.c_str(), param.c_str()); params::convert(_params, param); Loading Loading @@ -209,8 +209,11 @@ void pcap_offline_layer::receive_data(OCTETSTRING& data, params& params) { void pcap_offline_layer::Handle_Fd_Event_Readable(int fd) { //loggers::get_instance().log(">>> pcap_offline_layer::Handle_Fd_Event_Readable: %d", fd); char c[2]; float duration; // Process the packet at this layer loggers::get_instance().set_start_time(_time_key); this->receive_data(_o_data, _o_params); loggers::get_instance().set_stop_time(_time_key, duration); read(_fd[0], &c, 1); _resume.unlock(); } Loading ccsrc/Protocols/Pcap/pcap_offline_layer.hh +2 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,8 @@ class pcap_offline_layer : public layer, public PORT { params _o_params; OCTETSTRING _o_data; std::string _time_key; static void* run(void* p_this); public: void* thread(void); Loading Loading
ccsrc/Protocols/Pcap/pcap_cygwin_layer.cc 0 → 100755 +262 −0 Original line number Diff line number Diff line #if defined (__CYGWIN__) #define _GNU_SOURCE #include <unistd.h> #include <fcntl.h> #include <sys/stat.h> #include <errno.h> #include <chrono> #include <sstream> #include <iomanip> #include <Port.hh> #include "pcap_layer_factory.hh" #include "loggers.hh" #include <pcap.h> typedef struct { bpf_int32 tv_sec; /* seconds */ bpf_int32 tv_usec; /* microseconds */ }pcap_o_timeval; typedef struct pcap_o_pkthdr { pcap_o_timeval ts; /* time stamp */ bpf_u_int32 caplen; /* length of portion present */ bpf_u_int32 len; /* length this packet (off wire) */ }pcap_o_pkthdr; extern "C" int pcap_oid_get_request(pcap_t *p, bpf_u_int32 oid, void *data, size_t *lenp); static const char* _hexDigits = "0123456789ABCDEF"; static char * _bin2hex(char * hex, size_t hlen, const char * bin, size_t blen) { const unsigned char *b, *e; char * s; // sanity check if (hlen >= 0 && hlen < blen * 2) return NULL; b = (const unsigned char *)bin; e = b + blen - 1; s = hex + blen * 2; if (s < hex + hlen) *s = 0; for (; b <= e; e--){ *(--s) = _hexDigits[(*e) & 0xF]; *(--s) = _hexDigits[(*e) >> 4]; } return hex + blen * 2; } pcap_layer::pcap_layer(const std::string& p_type, const std::string& param) : layer(p_type), PORT(p_type.c_str()), _params(), _device(NULL), _running(FALSE), _time_key("pcap_layer::Handle_Fd_Event_Readable") { loggers::get_instance().log(">>> pcap_layer::pcap_layer: %s, %s", p_type.c_str(), param.c_str()); params::convert(_params, param); char error_buffer[PCAP_ERRBUF_SIZE]; params::const_iterator it; std::string nic; //network interface name bpf_u_int32 mask; // subnet mask bpf_u_int32 net; // ip address it = _params.find(params::nic); if ((it == _params.end()) || it->second.empty()) { loggers::get_instance().error("pcap_layer::pcap_layer: NIC must be specified"); return; } nic = std::string("\\Device\\NPF_{") + it->second + "}"; if (pcap_lookupnet(nic.c_str(), &net, &mask, error_buffer) != 0) { loggers::get_instance().error("pcap_layer::pcap_layer: pcap_layer::pcap_layer: Failed to fetch newtork address for device %s", nic.c_str()); } loggers::get_instance().log("pcap_layer::pcap_layer: Device %s Network address: %d", nic.c_str(), net); // Open the device _device = pcap_open_live(nic.c_str(), 65536, 1, 200, error_buffer); if (_device == NULL) { loggers::get_instance().error("pcap_layer::pcap_layer: Failed to open device %s", nic.c_str()); return; } // Setup filter std::string filter = ""; std::string mac_src; it = _params.find(params::mac_src); if (it != _params.end() && !it->second.empty()) { mac_src = it->second; } else { // Not found // determine it automatically #ifndef OID_802_3_CURRENT_ADDRESS #define OID_802_3_CURRENT_ADDRESS 0x01010102 #endif char mac[6] = {0}; size_t l = sizeof(mac); pcap_oid_get_request(_device, OID_802_3_CURRENT_ADDRESS, mac, &l); char buf[13]; *_bin2hex(buf, sizeof(buf), mac, 6) = 0; mac_src = buf; loggers::get_instance().user("pcap_layer::pcap_layer: local MAC is %s", mac_src.c_str()); } std::string mac_bc; it = _params.find(params::mac_bc); if (it != _params.end() && !it->second.empty()) mac_bc = it->second; else mac_bc = "ffffffffffff"; if(mac_bc == mac_src || mac_src.empty()) filter = "ether dst " + mac_bc; else filter = "( ether dst " + mac_bc + " or ether dst " + mac_src + " )"; if(! mac_src.empty()) // Reject ITS messages sent by this component filter += " and not ether src " + mac_src; // Add user defined filter it = _params.find(std::string("filter")); if ((it != _params.end()) && !it->second.empty()) { filter += std::string(" ") + it->second; } // Log final PCAP filter loggers::get_instance().user("pcap_layer::pcap_layer: Filter: %s", filter.c_str()); // setup filter { struct bpf_program f = {0}; if (pcap_compile(_device, &f, filter.c_str(), 1, PCAP_NETMASK_UNKNOWN) != 0) { loggers::get_instance().error("pcap_layer::pcap_layer: Failed to compile PCAP filter"); } else { if (pcap_setfilter(_device, &f) != 0) { loggers::get_instance().error("pcap_layer::pcap_layer: Failed to set PCAP filter"); } } pcap_freecode(&f); } _o_params.insert(std::pair<std::string, std::string>(std::string("timestamp"), std::string())); // create pipe and run thread if (pipe2(_fd, O_NONBLOCK) == -1) { loggers::get_instance().error("pcap_layer::pcap_layer: Failed to create a pipe: %s", ::strerror(errno)); } // Pass the pipe handler to the polling procedure loggers::get_instance().log("pcap_layer::pcap_layer: Call handler with descriptor %d", _fd[0]); Handler_Add_Fd_Read(_fd[0]); // Create the reader thread _thread = new std::thread(&pcap_layer::run, (void *)this); if (_thread == NULL) { loggers::get_instance().error("pcap_layer::pcap_layer: Failed to start offline thread"); } while (_running == FALSE) { std::this_thread::sleep_for(std::chrono::milliseconds(500)); } // Thread was started loggers::get_instance().log("<<< pcap_layer::pcap_layer"); } // End of ctor pcap_layer::~pcap_layer() { loggers::get_instance().log(">>> pcap_layer::~pcap_layer"); if (_device != NULL) { if (_thread != NULL) { _running = FALSE; // Wait for the working thread to terminate _thread->join(); loggers::get_instance().log("pcap_layer::~pcap_layer: Thread were stops"); // Cleanup delete _thread; close(_fd[0]); close(_fd[1]); } pcap_close(_device); } } // End of dtor void* pcap_layer::run(void* p_this) { pcap_layer& p = *static_cast<pcap_layer *>(p_this); return p.thread(); } void* pcap_layer::thread() { pcap_o_pkthdr *pkt_header; const u_char *pkt_data; unsigned char pkt_count = 0; loggers::get_instance().log(">>> pcap_layer::run"); _running = TRUE; // wait a bit before sending first packet std::this_thread::sleep_for(std::chrono::milliseconds(500)); while (_running) { // Loop while _running flag is up // get next frame int result = pcap_next_ex(_device, (struct pcap_pkthdr**)&pkt_header, &pkt_data); if(result == 0){ continue; } if(result < 0){ loggers::get_instance().log("<<< pcap_layer::run: error %s", pcap_geterr(_device)); break; } while(_running && !_resume.try_lock()) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); } #if 0 { char buf[128]; std::time_t t = pkt_header->ts.tv_sec; std::tm * pt = std::localtime( &t ); t = std::strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", pt); std::sprintf(buf+t, ".%06ld", pkt_header->ts.tv_usec); _o_params["timestamp"] = std::string(buf); } #else _o_params["timestamp"] = std::to_string(pkt_header->ts.tv_usec); #endif _o_data = OCTETSTRING(pkt_header->len, pkt_data); write(_fd[1], &pkt_count, 1);pkt_count++; } _running = FALSE; loggers::get_instance().log("<<< pcap_layer::run"); return NULL; } void pcap_layer::send_data(OCTETSTRING& data, params& params) { loggers::get_instance().log_msg(">>> pcap_layer::send_data: ", data); if (pcap_sendpacket(_device, static_cast<const unsigned char *>(data), data.lengthof()) == -1) { loggers::get_instance().error("pcap_layer::send_data: Failed to send packet: %s", pcap_geterr(_device)); } } void pcap_layer::receive_data(OCTETSTRING& data, params& params) { loggers::get_instance().log(">>> pcap_layer::receive_data: Received %d bytes", data.lengthof()); loggers::get_instance().log_to_hexa("Packet dump", data); // Pass the packet to the upper layers receive_to_all_layers(data, params); } void pcap_layer::Handle_Fd_Event_Readable(int fd) { char c[2]; float duration; loggers::get_instance().set_start_time(_time_key); this->receive_data(_o_data, _o_params); loggers::get_instance().set_stop_time(_time_key, duration); read(_fd[0], &c, 1); _resume.unlock(); } pcap_layer_factory pcap_layer_factory::_f; #endif //__CYGWIN__
ccsrc/Protocols/Pcap/pcap_cygwin_layer.hh 0 → 100755 +78 −0 Original line number Diff line number Diff line /*! * \file pcap_layer.hh * \brief Header file for ITS Offline Pcap port layer. * \author ETSI STF525 * \copyright ETSI Copyright Notification * No part may be reproduced except as authorized by written permission. * The copyright and the foregoing restriction extend to reproduction in all media. * All rights reserved. * \version 0.1 */ #pragma once #include <thread> #include <mutex> #include "t_layer.hh" #include "params.hh" #include <Octetstring.hh> class PORT; //! Forward declaration of TITAN class typedef struct pcap pcap_t; /*! * \class pcap_layer * \brief This class provides description of ITS PCAP port protocol layer */ class pcap_layer : public layer, public PORT { params _params; //! Layer parameters pcap_t* _device; //! Device handle std::thread* _thread; //! Thread handle, used to read PCAP file instead of NIC, used in file mode std::mutex _resume; bool _running; //! Set to true when the thread is running, used in file mode int _fd[2]; //! pipe to signal to Titan OCTETSTRING _o_data; params _o_params; std::string _time_key; static void* run(void* p_this); public: void* thread(void); public: //! \publicsection /*! * \brief Specialised constructor * Create a new instance of the pcap_layer class * \param[in] p_type \todo * \param[in] p_param \todo */ pcap_layer(const std::string& p_type, const std::string& param); /*! * \brief Default destructor */ virtual ~pcap_layer(); /*! * \virtual * \fn void send_data(OCTETSTRING& data, params& params); * \brief Send bytes formated data to the lower layers * \param[in] p_data The data to be sent * \param[in] p_params Some parameters to overwrite default value of the lower layers parameters */ virtual void send_data(OCTETSTRING& data, params& params); /*! * \virtual * \fn void receive_data(OCTETSTRING& data, params& params); * \brief Receive bytes formated data from the lower layers * \param[in] p_data The bytes formated data received * \param[in] p_params Some lower layers parameters values when data was received */ virtual void receive_data(OCTETSTRING& data, params& info); void Handle_Fd_Event_Readable(int fd); };
ccsrc/Protocols/Pcap/pcap_layer.cc +2 −50 Original line number Diff line number Diff line #if defined (__CYGWIN__) #define _GNU_SOURCE #endif #if 0 #include <unistd.h> #include <fcntl.h> #include <sys/stat.h> Loading @@ -11,27 +9,8 @@ #include "pcap_layer_factory.hh" #if defined (__CYGWIN__) typedef void* HANDLE; typedef unsigned int DWORD; extern "C" { DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds); HANDLE pcap_getevent(pcap_t *p); } typedef struct { bpf_int32 tv_sec; /* seconds */ bpf_int32 tv_usec; /* microseconds */ }pcap_o_timeval; typedef struct pcap_o_pkthdr { pcap_o_timeval ts; /* time stamp */ bpf_u_int32 caplen; /* length of portion present */ bpf_u_int32 len; /* length this packet (off wire) */ }pcap_o_pkthdr; #else typedef struct pcap_pkthdr pcap_o_pkthdr; typedef struct timeval pcap_o_timeval; #endif #include "loggers.hh" Loading @@ -51,11 +30,7 @@ pcap_layer::pcap_layer(const std::string& p_type, const std::string& param) : la bpf_u_int32 net; // ip address std::string nic; online = true; #ifdef __CYGWIN__ nic = std::string("\\Device\\NPF_{") + _params[params::nic] + "}"; #else nic = _params[params::nic]; #endif if (pcap_lookupnet(nic.c_str(), &net, &mask, error_buffer) != 0) { loggers::get_instance().error("pcap_layer::pcap_layer: pcap_layer::pcap_layer: Failed to fetch newtork address for device %s", nic.c_str()); } Loading @@ -69,13 +44,11 @@ pcap_layer::pcap_layer(const std::string& p_type, const std::string& param) : la if (pcap_setnonblock(_device, 1, error_buffer) != 0) { loggers::get_instance().error("pcap_layer::pcap_layer: Failed to set blocking mode: %s", error_buffer); } #if ! defined (__CYGWIN__) // Retrieve the device file handler _pcap_h = pcap_get_selectable_fd(_device); if (_pcap_h == -1) { loggers::get_instance().error("pcap_layer::pcap_layer: Failed to get device handler"); } #endif } else { // Check file name it = _params.find(std::string("file")); Loading Loading @@ -220,28 +193,6 @@ void* pcap_layer::thread() { catch (out_of_range& o) { }*/ } #if defined (__CYGWIN__) // check HANDLE emulation for pcap if(_fd[0] == _pcap_h) { HANDLE h = pcap_getevent(_device); _running = TRUE; while (_running) { // Loop while _running flag is up DWORD rc = WaitForSingleObject(h, 1000); if(rc == 0){ // event raised std::this_thread::sleep_for(std::chrono::milliseconds(1000)); if (_resume.try_lock() == TRUE) { // Previous packet was consumed, lock for the next one write(_fd[1], "\n", 1); // Any character will do the job } else { // not ready yet std::this_thread::sleep_for(std::chrono::milliseconds(100)); } }else if(rc == 0x00000102L) { // timeout }else { } } return NULL; } #endif // Let's go _running = TRUE; while (_running) { // Loop while _running flag is up Loading Loading @@ -322,3 +273,4 @@ void pcap_layer::Handle_Fd_Event_Readable(int fd) { pcap_layer_factory pcap_layer_factory::_f; #endif // !CYGWIN
ccsrc/Protocols/Pcap/pcap_offline_layer.cc +4 −1 Original line number Diff line number Diff line Loading @@ -32,7 +32,7 @@ typedef struct timeval pcap_o_timeval; #endif pcap_offline_layer::pcap_offline_layer(const std::string& p_type, const std::string& param) : layer(p_type), PORT(p_type.c_str()), _params(), _device(NULL), _running(FALSE) { layer(p_type), PORT(p_type.c_str()), _params(), _device(NULL), _running(FALSE), _time_key("pcap_offline_layer::Handle_Fd_Event_Readable") { loggers::get_instance().log(">>> pcap_offline_layer::pcap_offline_layer: %s, %s", p_type.c_str(), param.c_str()); params::convert(_params, param); Loading Loading @@ -209,8 +209,11 @@ void pcap_offline_layer::receive_data(OCTETSTRING& data, params& params) { void pcap_offline_layer::Handle_Fd_Event_Readable(int fd) { //loggers::get_instance().log(">>> pcap_offline_layer::Handle_Fd_Event_Readable: %d", fd); char c[2]; float duration; // Process the packet at this layer loggers::get_instance().set_start_time(_time_key); this->receive_data(_o_data, _o_params); loggers::get_instance().set_stop_time(_time_key, duration); read(_fd[0], &c, 1); _resume.unlock(); } Loading
ccsrc/Protocols/Pcap/pcap_offline_layer.hh +2 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,8 @@ class pcap_offline_layer : public layer, public PORT { params _o_params; OCTETSTRING _o_data; std::string _time_key; static void* run(void* p_this); public: void* thread(void); Loading