commsignia_layer.cc 7.97 KB
Newer Older
#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
unsigned char commsignia_layer::_fixed_header[12] = { 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAA, 0x0D, 0x00, 0x00 };

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
  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
  }
  //_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
  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);
}

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);

Yann Garcia's avatar
Yann Garcia committed
  const commsignia_layer::c2p_s_v1_tx_t* r = (const commsignia_layer::c2p_s_v1_tx_t*)p;
  loggers::get_instance().log("commsignia_layer::receive_data: version=%02x", r->s_header.u8_ver_type);
  loggers::get_instance().log("commsignia_layer::receive_data: timestamp1=%08x", ntohl(r->s_header.u32_tst_sec));
  loggers::get_instance().log("commsignia_layer::receive_data: timestamp2=%08x", ntohl(r->s_header.u32_tst_msec));
  loggers::get_instance().log("commsignia_layer::receive_data: primary_channel=%08x", ntohl(r->u8_primary_channel));
  loggers::get_instance().log("commsignia_layer::receive_data: secondary_channel=%08x", ntohl(r->u8_secondary_channel));
  loggers::get_instance().log("commsignia_layer::receive_data: antenna=%02x", r->u8_antenna);
  loggers::get_instance().log("commsignia_layer::receive_data: s8_tssi_ant_1=%d", r->s8_tssi_ant_1);
  loggers::get_instance().log("commsignia_layer::receive_data: s8_tssi_ant_2=%d", r->s8_tssi_ant_2);
  // Filtering on antenna index
Yann Garcia's avatar
Yann Garcia committed
  loggers::get_instance().log("commsignia_layer::receive_data: compare %02x with %02x", r->u8_antenna, static_cast<unsigned char>(std::stoi(_params[params::interface_id])));
  if (r->u8_antenna != std::stoi(_params[params::interface_id])) {
    // Discard packet
    loggers::get_instance().warning("commsignia_layer::receive_data: Discard packet due to wrong antenna id");
    return;
  } // else, continue

Yann Garcia's avatar
Yann Garcia committed
  const commsignia_layer::c2p_802_11p_hdr* h = (const commsignia_layer::c2p_802_11p_hdr*)(p + sizeof(commsignia_layer::c2p_s_v1_tx_t));
  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) {
Yann Garcia's avatar
Yann Garcia committed
    l = (const commsignia_layer::c2p_llc_hdr*)(p + sizeof(commsignia_layer::c2p_s_v1_tx_t) + sizeof(commsignia_layer::c2p_802_11p_hdr) + sizeof(commsignia_layer::c2p_qos_ctrl));
    length = sizeof(commsignia_layer::c2p_s_v1_tx_t) + sizeof(commsignia_layer::c2p_802_11p_hdr) + sizeof(commsignia_layer::c2p_qos_ctrl) + sizeof(commsignia_layer::c2p_llc_hdr);
Yann Garcia's avatar
Yann Garcia committed
    l = (const commsignia_layer::c2p_llc_hdr*)(p + sizeof(commsignia_layer::c2p_s_v1_tx_t) + sizeof(commsignia_layer::c2p_802_11p_hdr));
    length = sizeof(commsignia_layer::c2p_s_v1_tx_t) + sizeof(commsignia_layer::c2p_802_11p_hdr) + sizeof(commsignia_layer::c2p_llc_hdr);
Yann Garcia's avatar
Yann Garcia committed
  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);
  // 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;