commsignia_layer.cc 7.92 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
#include <algorithm>
#include <cctype>
#include <arpa/inet.h>

#include "commsignia_layer_factory.hh"

#include "loggers.hh"

#include "converter.hh"

Yann Garcia's avatar
Yann Garcia committed
11
12
unsigned char commsignia_layer::_fixed_header[12] = { 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAA, 0x0D, 0x00, 0x00 };

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
commsignia_layer::commsignia_layer(const std::string & p_type, const std::string & param) : layer(p_type), _params(), _c2p_recv{0}, _802_11p_hdr{0}, _c2p_llc_hdr{0}, _mac_src(), _eth_type() {
  loggers::get_instance().log(">>> commsignia_layer::commsignia_layer: %s, %s", to_string().c_str(), param.c_str());
  
  // Setup parameters
  params::convert(_params, param);
  params::const_iterator it = _params.find(params::mac_src);
  if (it == _params.cend()) {
    _params.insert(std::pair<std::string, std::string>(std::string("mac_src"), "000000000000"));
  }
  _mac_src = converter::get_instance().hexa_to_bytes(_params[params::mac_src]);
  it = _params.find(params::mac_bc);
  if (it == _params.cend()) {
    _params.insert(std::pair<std::string, std::string>(std::string("mac_bc"), "FFFFFFFFFFFF"));
  }
  it = _params.find(params::eth_type);
  if (it == _params.cend()) {
    _params.insert(std::pair<std::string, std::string>(std::string("eth_type"), "8947"));
  }
  _eth_type = converter::get_instance().hexa_to_bytes(_params[params::eth_type]);
  it = _params.find(params::interface_id);
  if (it == _params.cend()) {
    _params.insert(std::pair<std::string, std::string>(std::string("interface_id"), "1"));
  }
Yann Garcia's avatar
Yann Garcia committed
36
37
38
39
40
41
42
43
  it = _params.find(std::string("power_tx"));
  if (it == _params.cend()) {
    _params.insert(std::pair<std::string, std::string>(std::string("power_tx"), "20")); // 20db
  }
  it = _params.find(std::string("data_rate"));
  if (it == _params.cend()) {
    _params.insert(std::pair<std::string, std::string>(std::string("data_rate"), "12")); // 12 * 500Kbps = 6Mbps
  }
44
45
46
47
48
49
  //_params.log();
}

void commsignia_layer::send_data(OCTETSTRING& data, params& params) {
  loggers::get_instance().log_msg(">>> commsignia_layer::send_data: ", data);

Yann Garcia's avatar
Yann Garcia committed
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
  OCTETSTRING buffer(12, commsignia_layer::_fixed_header);
  buffer += int2oct(std::stoi(_params[params::interface_id]), 4);
  loggers::get_instance().log_msg("commsignia_layer::send_data: buffer: ", buffer);
  buffer += int2oct(std::stoi(_params[std::string("data_rate")]), 4);
  loggers::get_instance().log_msg("commsignia_layer::send_data: buffer: ", buffer);
  buffer += int2oct(0x80000000 & std::stoi(_params[std::string("power_tx")]), 4); // Negative number
  loggers::get_instance().log_msg("commsignia_layer::send_data: buffer: ", buffer);
  buffer += int2oct(7, 1); // MAC user priority
  // Destination MAC address
  params::const_iterator it = params.find(params::mac_dst); // Find in provided parameters, params
  if (it != params.cend()) {
    buffer = str2oct(CHARSTRING(it->second.c_str()));
  } else {
    it = _params.find(params::mac_dst);
    if (it != _params.cend()) {
      buffer = str2oct(CHARSTRING(it->second.c_str()));
    } else {
      buffer = str2oct(CHARSTRING(_params[params::mac_bc].c_str()));
    }
  }
  loggers::get_instance().log_msg("commsignia_layer::send_data: buffer: ", buffer);
  // Source MAC address
  it = params.find(params::mac_src); // Find in provided parameters, params
  if (it != params.cend()) {
    buffer += str2oct(CHARSTRING(it->second.c_str()));
  } else {
    buffer += str2oct(CHARSTRING(_params[params::mac_src].c_str()));
  }
  loggers::get_instance().log_msg("commsignia_layer::send_data: buffer: ", buffer);
  buffer += int2oct(0, 2); // Fixed
  loggers::get_instance().log_msg("commsignia_layer::send_data: buffer: ", buffer);
  buffer += int2oct(data.lengthof(), 2);
  loggers::get_instance().log_msg("commsignia_layer::send_data: buffer: ", buffer);
  buffer += data;
  
  loggers::get_instance().log_msg("commsignia_layer::send_data: ", buffer);
  send_to_all_layers(buffer, params);
87
88
89
90
91
92
93
94
}

void commsignia_layer::receive_data(OCTETSTRING& data, params& params) {
  loggers::get_instance().log_msg(">>> commsignia_layer::receive_data: ", data);
  
  const unsigned char* p = static_cast<const unsigned char *>(data);

  const commsignia_layer::c2p_recv* r = (const commsignia_layer::c2p_recv*)p;
Yann Garcia's avatar
Yann Garcia committed
95
96
97
98
99
100
101
102
  loggers::get_instance().log("commsignia_layer::receive_data: version=%02x", r->version);
  loggers::get_instance().log("commsignia_layer::receive_data: timestamp1=%08x", ntohl(r->timestamp_sec));
  loggers::get_instance().log("commsignia_layer::receive_data: timestamp2=%08x", ntohl(r->timestamp_msec));
  loggers::get_instance().log("commsignia_layer::receive_data: timestamp2=%08x", ntohl(r->timestamp_msec));
  loggers::get_instance().log("commsignia_layer::receive_data: antenna=%02x", r->antenna);
  loggers::get_instance().log("commsignia_layer::receive_data: rssi_ant2=%02x", r->rssi_ant2);
  loggers::get_instance().log("commsignia_layer::receive_data: noise_ant1=%02x", r->noise_ant1);
  loggers::get_instance().log("commsignia_layer::receive_data: noise_ant2=%02x", r->noise_ant2);
103
  // Filtering on antenna index
Yann Garcia's avatar
Yann Garcia committed
104
  loggers::get_instance().log("commsignia_layer::receive_data: compare %02x with %02x", r->antenna, static_cast<unsigned char>(std::strtoul(_params[params::interface_id].c_str(), NULL, 10)));
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
  if (r->antenna != static_cast<unsigned char>(std::strtoul(_params[params::interface_id].c_str(), NULL, 10))) {
    // Discard packet
    loggers::get_instance().warning("commsignia_layer::receive_data: Discard packet due to wrong antenna id");
    return;
  } // else, continue

  const commsignia_layer::c2p_802_11p_hdr* h = (const commsignia_layer::c2p_802_11p_hdr*)(p + sizeof(commsignia_layer::c2p_recv));
  //loggers::get_instance().log("commsignia_layer::receive_data: frame_ctrl=%04x", ntohs(h->frame_ctrl));
  OCTETSTRING dst = OCTETSTRING(6, (const unsigned char*)&h->dst_addr);
  loggers::get_instance().log_msg("commsignia_layer::receive_data: dst: ", dst);
  OCTETSTRING src = OCTETSTRING(6, (const unsigned char*)&h->src_addr);
  loggers::get_instance().log_msg("commsignia_layer::receive_data: src: ", src);

  // Filtering on source MAC address of the packet
  if (!std::equal(_mac_src.cbegin(), _mac_src.cend(), static_cast<const unsigned char*>(src))) {
    // Discard packet
    loggers::get_instance().warning("commsignia_layer::receive_data: Discard packet due to wrong comparison");
    return;
  } // else, continue
  const commsignia_layer::c2p_llc_hdr* l;
  int length;
  if ((ntohs(h->frame_ctrl) & 0xf000) == 0x8000) {
    l = (const commsignia_layer::c2p_llc_hdr*)(p + sizeof(commsignia_layer::c2p_recv) + sizeof(commsignia_layer::c2p_802_11p_hdr) + sizeof(commsignia_layer::c2p_qos_ctrl));
    length = sizeof(commsignia_layer::c2p_recv) + sizeof(commsignia_layer::c2p_802_11p_hdr) + sizeof(commsignia_layer::c2p_qos_ctrl) + sizeof(commsignia_layer::c2p_llc_hdr);
  } else {
    l = (const commsignia_layer::c2p_llc_hdr*)(p + sizeof(commsignia_layer::c2p_recv) + sizeof(commsignia_layer::c2p_802_11p_hdr));
    length = sizeof(commsignia_layer::c2p_recv) + sizeof(commsignia_layer::c2p_802_11p_hdr) + sizeof(commsignia_layer::c2p_llc_hdr);
  }
Yann Garcia's avatar
Yann Garcia committed
133
134
135
  loggers::get_instance().log("commsignia_layer::receive_data: dsap=%02x", l->dsap);
  loggers::get_instance().log("commsignia_layer::receive_data: ssap=%02x", l->ssap);
  loggers::get_instance().log("commsignia_layer::receive_data: type=%04x", l->type);
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
  // Check ether type
  if ((_eth_type[1] == (unsigned char)((l->type & 0xff00) >> 8)) && (_eth_type[0] == (unsigned char)(l->type & 0xff))) { // Warning: Network ordered bytes
    // Extract payload
    data = OCTETSTRING(data.lengthof() - length, length + static_cast<const unsigned char *>(data));
    //loggers::get_instance().log_msg("commsignia_layer::receive_data: payload for upper layer:", data);
    
    // Update params
    CHARSTRING s = oct2str(dst);
    params[params::mac_dst] = std::string(static_cast<const char *>(s));
    s = oct2str(src);
    params[params::mac_src] = std::string(static_cast<const char *>(s));
    
    receive_to_all_layers(data, params);
  } // else, nothing to do
}

commsignia_layer_factory commsignia_layer_factory::_f;