Compare Revisions

The credentials to download the source code are:
 Username: svnusers
 Password: svnusers

Ignore whitespace Rev 3321 → Rev 3322

/branches/STF525/ccsrc/Protocols/Pcap/pcap_cygwin_layer.cc
0,0 → 1,262
#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__
Property changes:
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+URL Id
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: Protocols/Pcap/pcap_cygwin_layer.hh
===================================================================
--- Protocols/Pcap/pcap_cygwin_layer.hh (nonexistent)
+++ Protocols/Pcap/pcap_cygwin_layer.hh (revision 3322)
@@ -0,0 +1,78 @@
+/*!
+ * \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);
+};
/Protocols/Pcap/pcap_cygwin_layer.hh
Property changes:
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+URL Id
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: Protocols/Pcap/pcap_layer.cc
===================================================================
--- Protocols/Pcap/pcap_layer.cc (revision 3321)
+++ Protocols/Pcap/pcap_layer.cc (revision 3322)
@@ -1,6 +1,4 @@
-#if defined (__CYGWIN__)
-#define _GNU_SOURCE
-#endif
+#if 0
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
@@ -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"
@@ -51,11 +30,7 @@
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());
}
@@ -69,13 +44,11 @@
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"));
@@ -220,28 +193,6 @@
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
@@ -322,3 +273,4 @@
pcap_layer_factory pcap_layer_factory::_f;
+#endif // !CYGWIN
/branches/STF525/ccsrc/Protocols/Pcap/pcap_offline_layer.cc
32,7 → 32,7
#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);
 
209,8 → 209,11
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();
}
/branches/STF525/ccsrc/Protocols/Pcap/pcap_offline_layer.hh
39,6 → 39,8
params _o_params;
OCTETSTRING _o_data;
 
std::string _time_key;
 
static void* run(void* p_this);
public:
void* thread(void);