geonetworking_layer.cc 58.4 KB
Newer Older
1
2
3
4
5
#include <thread>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>

garciay's avatar
garciay committed
6
#include "geonetworking_types.hh"
7

garciay's avatar
garciay committed
8
#include "geonetworking_layer_factory.hh"
9

10
11
#include "loggers.hh"

garciay's avatar
garciay committed
12
13
#include "security_services.hh"

garciay's avatar
garciay committed
14
15
#include "base_time.hh"

Yann Garcia's avatar
Yann Garcia committed
16
17
#include "registration.hh"

18
19
#include "converter.hh"

20
21
using namespace LibItsGeoNetworking__TypesAndValues;

Yann Garcia's avatar
Yann Garcia committed
22
geonetworking_layer::geonetworking_layer(const std::string & p_type, const std::string & p_param) : t_layer<LibItsGeoNetworking__TestSystem::GeoNetworkingPort>(p_type), _params(), _codec(), _beacon(nullptr), _gbc_packet(nullptr), _shb_packet(nullptr), _tsb_packet(nullptr),_uni_packet(nullptr), _ls_reply(nullptr), _location_table(), _pass_beacon_table(), _device_mode{false}, _secured_mode{false}, _encrypted_mode{false}, _enable_security_checks{false}, _sendData(), _timerid{0}, _sev{0}, _its{0}, _freq_nanosecs(0), _mask{0}, _sa{0}, _sequence_number{0}, _latitude{0}, _longitude{0} {
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
  loggers::get_instance().log(">>> geonetworking_layer::geonetworking_layer: %s, %s", to_string().c_str(), p_param.c_str());

  init(p_type, p_param);
} // End of constructor

geonetworking_layer::~geonetworking_layer() {
  loggers::get_instance().log(">>> geonetworking_layer::~geonetworking_layer");

  if (_timerid != 0) {
    timer_delete(_timerid);
  }
  if (_beacon != nullptr) {
    delete _beacon;
  }
  if (_gbc_packet != nullptr) {
    delete _gbc_packet;
  }
  if (_shb_packet != nullptr) {
    delete _shb_packet;
  }
garciay's avatar
garciay committed
43
44
45
  if (_tsb_packet != nullptr) {
    delete _tsb_packet;
  }
Yann Garcia's avatar
Yann Garcia committed
46
47
48
  if (_uni_packet != nullptr) {
    delete _uni_packet;
  }
49
50
51
52
53
54
55
  if (_ls_reply != nullptr) {
    delete _ls_reply;
  }
} // End of destructor

void geonetworking_layer::init(const std::string & p_type, const std::string & p_param) {
  loggers::get_instance().log(">>> geonetworking_layer::init: %s, %s", to_string().c_str(), p_param.c_str());
56
57
  
  // Setup parameters
58
  params::convert(_params, p_param);
59
  // Sanity checks
garciay's avatar
garciay committed
60
  params::const_iterator it = _params.find(params::latitude);
61
  if (it != _params.cend()) {
62
    _latitude = converter::get_instance().string_to_int(it->second);
63
  }
garciay's avatar
garciay committed
64
  it = _params.find(params::longitude);
65
  if (it != _params.cend()) {
66
    _longitude = converter::get_instance().string_to_int(it->second);
67
68
  }
  OCTETSTRING ll_address;
garciay's avatar
garciay committed
69
  it = _params.find(params::ll_address);
70
71
72
73
  if (it != _params.cend()) {
    ll_address = str2oct(CHARSTRING(it->second.c_str()));
  }
  INTEGER distanceA = 1000; // 1km
garciay's avatar
garciay committed
74
  it = _params.find(params::distanceA);
75
  if (it != _params.cend()) {
76
    distanceA = converter::get_instance().string_to_int(it->second);
77
78
  }
  INTEGER distanceB = 1000; // 1Km
garciay's avatar
garciay committed
79
  it = _params.find(params::distanceB);
80
  if (it != _params.cend()) {
81
    distanceB = converter::get_instance().string_to_int(it->second);
82
83
  }
  INTEGER angle = 0;
garciay's avatar
garciay committed
84
  it = _params.find(params::angle);
85
  if (it != _params.cend()) {
86
    angle = converter::get_instance().string_to_int(it->second);
87
  }
88
  INTEGER station_type = 5; // passangerCar
garciay's avatar
garciay committed
89
  it = _params.find(params::station_type);
90
91
92
93
  if (it != _params.cend()) {
    station_type = converter::get_instance().string_to_int(it->second);
  }
  INTEGER country = 0;
garciay's avatar
garciay committed
94
  it = _params.find(params::country);
95
96
97
98
  if (it != _params.cend()) {
    country = converter::get_instance().string_to_int(it->second);
  }
  INTEGER type_of_address = 1; // Manual
garciay's avatar
garciay committed
99
  it = _params.find(params::type_of_address);
100
101
102
103
  if (it != _params.cend()) {
    type_of_address = converter::get_instance().string_to_int(it->second);
  }
  
garciay's avatar
garciay committed
104
  it = _params.find(params::device_mode);
105
  if (it != _params.cend()) {
106
    _device_mode = (1 == converter::get_instance().string_to_int(it->second));
107
  }
garciay's avatar
garciay committed
108
  it = _params.find(params::secured_mode);
garciay's avatar
garciay committed
109
110
  if (it != _params.cend()) {
    _secured_mode = (1 == converter::get_instance().string_to_int(it->second));
111
112
  } else {
    _params.insert(std::pair<std::string, std::string>(std::string("secured_mode"), "0"));
garciay's avatar
garciay committed
113
  }
garciay's avatar
garciay committed
114
  it = _params.find(params::encrypted_mode);
115
116
  if (it != _params.cend()) {
    _encrypted_mode = (1 == converter::get_instance().string_to_int(it->second));
117
118
  } else {
    _params.insert(std::pair<std::string, std::string>(std::string("encrypted_mode"), "0"));
119
  }
garciay's avatar
garciay committed
120
  it = _params.find(params::enable_security_checks);
garciay's avatar
garciay committed
121
122
123
  if (it != _params.cend()) {
    _enable_security_checks = (1 == converter::get_instance().string_to_int(it->second));
  }
garciay's avatar
garciay committed
124
  
125
  // Add broadcast address if needed
garciay's avatar
garciay committed
126
  it = _params.find(params::its_aid);
garciay's avatar
garciay committed
127
  if (it == _params.cend()) {
garciay's avatar
garciay committed
128
    _params.insert(std::pair<std::string, std::string>(std::string("its_aid"), "141"));
garciay's avatar
garciay committed
129
  }
garciay's avatar
garciay committed
130
  it = _params.find(params::mac_bc);
131
132
133
  if (it == _params.cend()) {
    _params.insert(std::pair<std::string, std::string>(std::string("mac_bc"), "FFFFFFFFFFFF"));
  }
garciay's avatar
garciay committed
134
  
garciay's avatar
garciay committed
135
  // Set up default security parameters value
136
  if (_secured_mode || _encrypted_mode) {
garciay's avatar
garciay committed
137
    loggers::get_instance().log("geonetworking_layer::geonetworking_layer: Setup secured mode");
138
    setup_secured_mode();
garciay's avatar
garciay committed
139
  }
garciay's avatar
garciay committed
140
141

  // Automatic beaconing mode
142
  fill_beacon(ll_address, station_type, country, type_of_address);
garciay's avatar
garciay committed
143
  params::const_iterator i = _params.find(params::beaconing);
144
145
146
147
148
  if ((i != _params.cend()) && (i->second.compare("1") == 0)) { // Immediate beaconing was requested
    // Prepare beaconing operation
    start_beaconing();
  }

149
  // Fill packet templates
150
151
152
  fill_gbc_packet(ll_address, _latitude, _longitude, distanceA, distanceB, angle);// TODO Check if GeoBroadcastArea lat/lon are identical to lat/lon of the Test System
  fill_shb_packet(ll_address);
  fill_tsb_packet(ll_address);
Yann Garcia's avatar
Yann Garcia committed
153
  fill_uni_packet(ll_address);
154
155
156
  fill_ls_reply(ll_address);
  
  // Register this object for AdapterControlPort
garciay's avatar
garciay committed
157
158
  loggers::get_instance().log("geonetworking_layer::geonetworking_layer: Register %s/%p", p_type.c_str(), this);
  registration<geonetworking_layer>::get_instance().add_item(p_type, this);
159
160
161

  // Add 4 leap seconds to convert to TAI (as Feb 2019)
  base_time::get_instance().set_leap_delay_us(4 * 1000000); // TODO Set it as parameter
162
} // End of init_params
163

garciay's avatar
garciay committed
164
void geonetworking_layer::sendMsg(const LibItsGeoNetworking__TestSystem::GeoNetworkingReq& p, params& params) {
garciay's avatar
garciay committed
165
  loggers::get_instance().log(">>> geonetworking_layer::sendMsg");
166
167
168
169

  // Encode GeoNetworking PDU
  OCTETSTRING data;
  _codec.encode(p.msgOut(), data);
garciay's avatar
garciay committed
170
  send_data(data, _params);
171
172
}

garciay's avatar
garciay committed
173
void geonetworking_layer::send_data(OCTETSTRING& data, params& params) {
garciay's avatar
garciay committed
174
  loggers::get_instance().log_msg(">>> geonetworking_layer::send_data: ", data);
175
  params.log();
176
177

  if (_device_mode) { // Need to build a GN packet
garciay's avatar
garciay committed
178
179
    params[params::certificate] = _params[params::certificate];
    params[params::hash] = _params[params::hash];
180
    params[params::signature] = _params[params::signature]; // TODO Should be removed
181
    if (build_geonetworking_pdu(data, params) != 0) {
182
183
184
      return;
    }
  }
Yann Garcia's avatar
Yann Garcia committed
185
  if (_secured_mode) { // Add Security support
garciay's avatar
garciay committed
186
    if (build_secured_pdu(data, params) != 0) {
garciay's avatar
garciay committed
187
188
189
      return;
    }
  }
190
191
192
193
194
195
  
  // TODO To be removed
  while (_sendData.try_lock() == FALSE) {
    // not ready yet
    std::this_thread::sleep_for(std::chrono::milliseconds(1));
  } // End of 'while' statement
garciay's avatar
garciay committed
196
  send_to_all_layers(data, params);
197
  _sendData.unlock();
garciay's avatar
garciay committed
198
  loggers::get_instance().log("<<< geonetworking_layer::send_data");
199
200
}

filatov's avatar
filatov committed
201
202
203
const TTCN_RAWdescriptor_t _intx_raw_= {RAW_INTX,SG_NO,ORDER_MSB,ORDER_MSB,ORDER_LSB,ORDER_MSB,EXT_BIT_NO,ORDER_LSB,ORDER_LSB,TOP_BIT_INHERITED,0,0,0,8,0,NULL,-1,CharCoding::UNKNOWN};
const TTCN_Typedescriptor_t _intx_descr_={"IntX", NULL, &_intx_raw_, NULL, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE};

garciay's avatar
garciay committed
204
void geonetworking_layer::receive_data(OCTETSTRING& data, params& params) { 
garciay's avatar
garciay committed
205
  loggers::get_instance().log_msg(">>> geonetworking_layer::receive_data: ", data);
garciay's avatar
garciay committed
206
207

  // Check security mode
garciay's avatar
garciay committed
208
  IEEE1609dot2::Ieee1609Dot2Data ieee_1609dot2_data;
garciay's avatar
garciay committed
209
210
211
  LibItsGeoNetworking__TypesAndValues::BasicHeader basic_header;
  decode_basic_header(data, basic_header);
  if ((int)basic_header.nextHeader() == 2) { // Verify and extract the GeoNetworking Secured Packet as specified in ETSI EN 302 636-4-1 V1.3.1 (2017-08) Clause 9.6.1 Composition of the Basic Header
212
    unsigned int basic_header_len = 4;// FIXME How to retrive the BasicHeader length basic_header.get_descriptor()->raw->fieldlength / 8;
garciay's avatar
garciay committed
213
    loggers::get_instance().log("geonetworking_layer::receive_data: basic_header_len = %d", basic_header_len);
garciay's avatar
garciay committed
214
215
    // Verify and extract the GeoNetworking Secured Packet as specified in ETSI EN 302 636-4-1 V1.3.1 (2017-08) Clause 9.4 GeoNetworking Secured Packet
    OCTETSTRING unsecured_gn_payload;
216
    OCTETSTRING secured_data = OCTETSTRING(data.lengthof() - basic_header_len, static_cast<const unsigned char*>(data) + basic_header_len);
217
    ///////////////////
garciay's avatar
garciay committed
218
    // FIXME Check what to do with this!
219
    if (*static_cast<const unsigned char*>(secured_data) == 0x02) { // This is the old Security version format, discard it
YannGarcia's avatar
YannGarcia committed
220
221
222
223
        loggers::get_instance().warning("geonetworking_layer::receive_data: Security error");
        if (_enable_security_checks) {
          return;
        }
filatov's avatar
filatov committed
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
      INTEGER n; int r;
      TTCN_Buffer buf(secured_data);
      loggers::get_instance().warning("geonetworking_layer::receive_data: Old security format, parse manualy");

      buf.increase_pos(1); // skip version
      n.decode(_intx_descr_, buf, TTCN_EncDec::CT_RAW);
      if(n > (int)buf.get_read_len()){
        loggers::get_instance().warning("geonetworking_layer::receive_data: Broken security headers");
    	return;
      }
      buf.increase_pos((int)n); // skip headers

      // payload type
      r = *buf.get_read_data();
      buf.increase_pos(1);
      if(r != 3){
        n.decode(_intx_descr_, buf, TTCN_EncDec::CT_RAW);
        //payload length
          if(n > (int)buf.get_read_len()){
            loggers::get_instance().warning("geonetworking_layer::receive_data: Broken security payload");
        	return;
          }
          unsecured_gn_payload = OCTETSTRING(n, buf.get_read_data());
      }
YannGarcia's avatar
YannGarcia committed
248
    } else {
filatov's avatar
filatov committed
249
250
251
252
253
254
      ///////////////////
      if (security_services::get_instance().verify_and_extract_gn_payload(secured_data, _enable_security_checks, ieee_1609dot2_data, unsecured_gn_payload, params) != 0) {
        loggers::get_instance().warning("geonetworking_layer::receive_data: Security error");
        if (_enable_security_checks) {
          return;
        }
garciay's avatar
garciay committed
255
256
257
      }
    }
    // Update data
garciay's avatar
garciay committed
258
    loggers::get_instance().log_msg("geonetworking_layer::receive_data: Unsecured payload: ", unsecured_gn_payload);
259
    data = OCTETSTRING(basic_header_len, static_cast<const unsigned char*>(data)) + unsecured_gn_payload;
garciay's avatar
garciay committed
260
261
  }
  
262
  // Decode the payload
garciay's avatar
garciay committed
263
  loggers::get_instance().log_msg("geonetworking_layer::receive_data: Geonetworking payload to decode: ", data);
264
265
  LibItsGeoNetworking__TestSystem::GeoNetworkingInd ind;
  _codec.decode(data, ind.msgIn(), &params);
garciay's avatar
garciay committed
266
  if (ind.msgIn().is_bound()) {
garciay's avatar
garciay committed
267
268
269
270
271
    // Update optional securedMsg field if required
    if (ieee_1609dot2_data.is_bound()) {
      ind.msgIn().gnPacket().securedMsg() = OPTIONAL<IEEE1609dot2::Ieee1609Dot2Data>(ieee_1609dot2_data);
    } // else, nothing to do
    // Update context
272
273
274
275
    const LibItsGeoNetworking__TypesAndValues::LongPosVector* sopv = nullptr;
    const LibItsGeoNetworking__TypesAndValues::GnNonSecuredPacket& p = ind.msgIn().gnPacket().packet();
    const LibItsGeoNetworking__TypesAndValues::HeaderTST& htst = p.commonHeader().headerTST();
    if (p.extendedHeader().ispresent()) { // Update location table
276
      const LibItsGeoNetworking__TypesAndValues::ExtendedHeader& ex = p.extendedHeader();
277
278
279
280
281
282
283
284
285
286
287
288
289
290
      if (htst.ischosen(LibItsGeoNetworking__TypesAndValues::HeaderTST::ALT_beaconHdr)) { // Receive a beacon
        sopv = &ex.beaconHeader().srcPosVector();
      } else if (htst.ischosen(LibItsGeoNetworking__TypesAndValues::HeaderTST::ALT_tsbHdr)) { // Receive a topologicallyScopeBroadcast
        if (ex.ischosen(LibItsGeoNetworking__TypesAndValues::ExtendedHeader::ALT_tsbHeader)) {
          sopv = &ex.tsbHeader().srcPosVector();
        } else {
          sopv = &ex.shbHeader().srcPosVector();
        }
      } else if (htst.ischosen(LibItsGeoNetworking__TypesAndValues::HeaderTST::ALT_geoBroadcastHdr)) {
        sopv = &ex.geoBroadcastHeader().srcPosVector();
      } else if (htst.ischosen(LibItsGeoNetworking__TypesAndValues::HeaderTST::ALT_lsHdr)) { // Receive a location service
        if (ex.ischosen(LibItsGeoNetworking__TypesAndValues::ExtendedHeader::ALT_lsRequestHeader)) { // Receive a LocationService/LsRequest
          sopv = &ex.lsRequestHeader().srcPosVector();
          // TODO Send LsReply if we are not in context of GN ATS in case of non GN test suite
291
292
293
294
295
          if (_device_mode) {
            // Update _ls_reply
            ExtendedHeader* eh = static_cast<ExtendedHeader *>(_ls_reply->gnPacket().packet().extendedHeader().get_opt_value());
            if (eh != nullptr) {
              // Update sequence number
296
              eh->lsReplyHeader().seqNumber() = _sequence_number++;
297
298
299
300
301
              // Update destination
              eh->lsReplyHeader().dstPosVector().gnAddr() = sopv->gnAddr();
              eh->lsReplyHeader().dstPosVector().latitude() = sopv->latitude();
              eh->lsReplyHeader().dstPosVector().longitude() = sopv->longitude();
              // Update timestamp
Yann Garcia's avatar
Yann Garcia committed
302
              eh->lsReplyHeader().srcPosVector().timestamp__().set_long_long_val(base_time::get_instance().get_its_current_time_mod_ms());
303
304
              eh->lsReplyHeader().dstPosVector().timestamp__() = eh->lsReplyHeader().srcPosVector().timestamp__();
              
garciay's avatar
garciay committed
305
              loggers::get_instance().log_msg("geonetworking_layer::receive_data: ", *_ls_reply);
306
307
308
309
310
              
              // send it
              // Encode GeoNetworking PDU
              OCTETSTRING os;
              _codec.encode(*_ls_reply, os);
311
              // Apply signature
garciay's avatar
garciay committed
312
              if (_secured_mode) {
313
                if (build_secured_pdu(data, _params) != 0) {
garciay's avatar
garciay committed
314
315
316
                  return;
                }
              }
317
318
319
320
321
322
              // Send it
              // TODO To be removed
              while (_sendData.try_lock() == FALSE) {
                // not ready yet
                std::this_thread::sleep_for(std::chrono::milliseconds(1));
              } // End of 'while' statement
garciay's avatar
garciay committed
323
              send_to_all_layers(os, params);
324
325
              _sendData.unlock();
            } else {
garciay's avatar
garciay committed
326
              loggers::get_instance().error("geonetworking_layer::send_data: Wrong cast");
327
328
329
              return;
            }
          }
330
331
332
333
334
335
336
337
        } else {
          sopv = &ex.lsReplyHeader().srcPosVector();
        }
      } else if (htst.ischosen(LibItsGeoNetworking__TypesAndValues::HeaderTST::ALT_geoAnycastHdr)) { // Receive a GeoAnycast
        sopv = &ex.geoAnycastHeader().srcPosVector();
      } else if (htst.ischosen(LibItsGeoNetworking__TypesAndValues::HeaderTST::ALT_geoUnicastHdr)) {
        sopv = &ex.geoUnicastHeader().srcPosVector();
      } // else, nothing to do
garciay's avatar
garciay committed
338
      loggers::get_instance().log("geonetworking_layer::receive_data: sopv is bound: %d", sopv->is_bound());
339
340
341
342
343
344
345
346
      if(sopv->is_bound()) {
        const LibItsGeoNetworking__TypesAndValues::LongPosVector& lpv = *sopv;
        _location_table.add_entry(lpv);
      }
    }
    
    // By default incoming beacons are filtered by the test adapter
    if (htst.ischosen(LibItsGeoNetworking__TypesAndValues::HeaderTST::ALT_beaconHdr)) {
YannGarcia's avatar
YannGarcia committed
347
      loggers::get_instance().log_msg("geonetworking_layer::receive_data: Pass beaconing filtering: ", sopv->gnAddr().mid());
348
      if (_pass_beacon_table.empty()) { // Discard beacon
garciay's avatar
garciay committed
349
        loggers::get_instance().log("geonetworking_layer::receive_data: Pass beaconing table empty, discard it");
350
351
352
        return;
      } else { // Check beacon filter for StartPassBeaconing/Stop
        if (!_pass_beacon_table.has_entry(sopv->gnAddr().mid())) { // Discard beacon
garciay's avatar
garciay committed
353
          loggers::get_instance().log_msg("geonetworking_layer::receive_data: Not in pass beaconing table, discard it", *sopv);
354
355
356
357
          return;
        } // else, continue
      }
    } // else, continue
garciay's avatar
garciay committed
358
359
  } else {
    // Inavlid GeoNetworking payload, discard it
garciay's avatar
garciay committed
360
    loggers::get_instance().warning("geonetworking_layer::receive_data: Failed to decode payload, discard it");
garciay's avatar
garciay committed
361
362
    return;
  }
363
364
365

  // Add lower layers parameters
  // 1. Destination MAC address
garciay's avatar
garciay committed
366
  params::const_iterator it = params.find(params::mac_dst);
367
  if (it != params.cend()) {
garciay's avatar
garciay committed
368
    loggers::get_instance().log("geonetworking_layer::receive_data: dst=%s", it->second.c_str());
369
370
371
372
373
    ind.macDestinationAddress() = str2oct(CHARSTRING(it->second.c_str()));
  } else {
    ind.macDestinationAddress() = str2oct(CHARSTRING(_params["mac_bc"].c_str()));
  }
  // 2. ssp
374
  it = params.find(params::ssp);
375
  if (it != params.cend()) {
garciay's avatar
garciay committed
376
    loggers::get_instance().log("geonetworking_layer::receive_data: ssp=%s", it->second.c_str());
garciay's avatar
garciay committed
377
    ind.ssp() = oct2bit(str2oct(CHARSTRING(it->second.c_str())));
378
379
380
381
  } else {
    ind.ssp().set_to_omit();
  }
  // 3. its_aid
garciay's avatar
garciay committed
382
  it = params.find(params::its_aid);
383
  if (it != params.cend()) {
garciay's avatar
garciay committed
384
    loggers::get_instance().log("geonetworking_layer::receive_data: its_aid=%s", it->second.c_str());
385
386
387
388
389
390
    ind.its__aid() = std::stoi(it->second.c_str());
  } else {
    ind.its__aid().set_to_omit();
  }
  
  // Pass the GeoNetworking raw payload to the upper layers if any
garciay's avatar
garciay committed
391
  it = params.find(params::gn_payload);
392
  if (it != params.cend()) {
garciay's avatar
garciay committed
393
    loggers::get_instance().log("geonetworking_layer::receive_data: gn_payload=%s", it->second.c_str());
394
    OCTETSTRING os(str2oct(CHARSTRING(it->second.c_str())));
garciay's avatar
garciay committed
395
    receive_to_all_layers(os, params);
396
  } else {
garciay's avatar
garciay committed
397
    loggers::get_instance().warning("geonetworking_layer::receive_data: No payload to pass to upper layers");
398
  }
399
  
400
  // Pass it to the ports
garciay's avatar
garciay committed
401
  to_all_upper_ports(ind, params);
402
403
}

garciay's avatar
garciay committed
404
OCTETSTRING geonetworking_layer::trigger_ac_event(OCTETSTRING& data, params& params)
405
{
garciay's avatar
garciay committed
406
  loggers::get_instance().log_to_hexa(">>> geonetworking_layer::trigger_ac_event: ", data);
407
408
409
410
411


  return int2oct(0, 2);  
} // End of trigger_ac_event method

garciay's avatar
garciay committed
412
413
414
void geonetworking_layer::start_beaconing() {
  loggers::get_instance().log(">>> geonetworking_layer::start_beaconing");
  //loggers::get_instance().log_msg("geonetworking_layer::start_beaconing: _beacon=", *_beacon);
415
416

  // Establish handler for timer signal
garciay's avatar
garciay committed
417
  loggers::get_instance().log("geonetworking_layer::start_beaconing: Establishing handler for signal %d\n", _signal_id);
418
419
420
  _sa.sa_flags = SA_SIGINFO;
  _sa.sa_sigaction = timer_irq_sigalrm_handler;
  sigemptyset(&_sa.sa_mask);
421
  if (sigaction(_signal_id, &_sa, nullptr) == -1) {
garciay's avatar
garciay committed
422
    loggers::get_instance().error("geonetworking_layer::start_beaconing: Sigaction failure: %d", errno);
423
424
  }
  // Block timer signal temporarily
garciay's avatar
garciay committed
425
  loggers::get_instance().log("geonetworking_layer::start_beaconing: Blocking signal %d\n", _signal_id);
426
427
  sigemptyset(&_mask);
  sigaddset(&_mask, _signal_id);
428
  if (sigprocmask(SIG_SETMASK, &_mask, nullptr) == -1) {
garciay's avatar
garciay committed
429
    loggers::get_instance().error("geonetworking_layer::start_beaconing: Sigprocmask failure: %d", errno);
430
431
432
433
  }	
  // Create the timer 
  _sev.sigev_notify = SIGEV_SIGNAL;
  _sev.sigev_signo = _signal_id; // Use signal alarm
garciay's avatar
garciay committed
434
  _sev.sigev_value.sival_ptr = this; // The geonetworking_layer object address
435
  if (timer_create(CLOCK_REALTIME, &_sev, &_timerid) == -1) {
garciay's avatar
garciay committed
436
    loggers::get_instance().error("geonetworking_layer::start_beaconing: Timer failure: %d", errno);
437
  }
garciay's avatar
garciay committed
438
  loggers::get_instance().log("geonetworking_layer::start_beaconing: timer ID is 0x%x\n", (long)_timerid);
439
440
  // Start the timer
  unsigned int expiry = 1000; // Default expiry time 1000ms
garciay's avatar
garciay committed
441
  params::const_iterator i = _params.find("expiry");
442
  if (i != _params.cend()) {
443
    expiry = static_cast<unsigned int>(std::strtoul(i->second.c_str(), nullptr, 10));
444
445
446
447
448
449
  }
  _freq_nanosecs = expiry * 1000000;
  _its.it_value.tv_sec = _freq_nanosecs / 1000000000;
  _its.it_value.tv_nsec = _freq_nanosecs % 1000000000;
  _its.it_interval.tv_sec = _its.it_value.tv_sec;
  _its.it_interval.tv_nsec = _its.it_value.tv_nsec;
450
  if (timer_settime(_timerid, 0, &_its, nullptr) == -1) {
garciay's avatar
garciay committed
451
    loggers::get_instance().error("geonetworking_layer::start_beaconing: Sigprocmask failure: %d", errno);
452
453
  }
  // Unlock the timer signal, so that timer notification can be delivered
garciay's avatar
garciay committed
454
  loggers::get_instance().log("geonetworking_layer::start_beaconing: Unblocking signal %d\n", _signal_id);
455
  if (sigprocmask(SIG_UNBLOCK, &_mask, nullptr) == -1) {
garciay's avatar
garciay committed
456
    loggers::get_instance().error("geonetworking_layer::start_beaconing: Sigprocmask failure: %d", errno);
457
458
459
  }
} // End of start_beaconing method

garciay's avatar
garciay committed
460
461
void geonetworking_layer::start_beaconing(const LibItsGeoNetworking__TypesAndValues::GeoNetworkingPdu& p_beacon) {
  loggers::get_instance().log_msg(">>> geonetworking_layer::start_beaconing", p_beacon);
462
463
464
465
466
467
468
469
470
471

  // Initialize the beacon
  if (_beacon != nullptr) {
    delete _beacon;
  }
  _beacon = new LibItsGeoNetworking__TypesAndValues::GeoNetworkingPdu(p_beacon);

  start_beaconing(); // TODO Refined adding a boolean return code
} // End of start_beaconing method

garciay's avatar
garciay committed
472
473
void geonetworking_layer::stop_beaconing() {
  loggers::get_instance().log(">>> geonetworking_layer::stop_beaconing");
474
475
  
  // Block timer signal temporarily
garciay's avatar
garciay committed
476
  loggers::get_instance().log("geonetworking_layer::stop_beaconing: Blocking signal %d\n", _signal_id);
477
478
  sigemptyset(&_mask);
  sigaddset(&_mask, _signal_id);
479
  if (sigprocmask(SIG_SETMASK, &_mask, nullptr) == -1) {
garciay's avatar
garciay committed
480
    loggers::get_instance().error("geonetworking_layer::stop_beaconing: Sigprocmask failure: %d", errno);
481
482
483
484
485
  }	
  timer_delete(_timerid);
  _timerid = 0;
} // End of stop_beaconing method

garciay's avatar
garciay committed
486
487
void geonetworking_layer::send_beacon() {
  loggers::get_instance().log(">>> geonetworking_layer::send_beacon");
488
489
  
  ExtendedHeader* eh = static_cast<ExtendedHeader *>(_beacon->gnPacket().packet().extendedHeader().get_opt_value());
490
  if (eh == nullptr) {
garciay's avatar
garciay committed
491
    loggers::get_instance().error("geonetworking_layer::send_beacon: Wrong cast");
492
493
  }
  // Update timestamp
Yann Garcia's avatar
Yann Garcia committed
494
  eh->beaconHeader().srcPosVector().timestamp__().set_long_long_val((unsigned int)base_time::get_instance().get_its_current_time_mod_ms());
garciay's avatar
garciay committed
495
  //loggers::get_instance().log_msg("geonetworking_layer::send_beacon: ", *_beacon);
496
497
498
499
  // Encode message using TITAN because of payload in omited
  TTCN_Buffer encoding_buffer;
  _beacon->encode(*(_beacon->get_descriptor()), encoding_buffer, TTCN_EncDec::CT_RAW);
  OCTETSTRING data(encoding_buffer.get_len(), encoding_buffer.get_data());
garciay's avatar
garciay committed
500
  params params(_params);
Yann Garcia's avatar
Yann Garcia committed
501
  if (_secured_mode) { // Apply Security
502
    if (build_secured_pdu(data, _params) != 0) {
garciay's avatar
garciay committed
503
504
505
      return;
    }
  }
506
  // Send it
507
508
509
510
511
  // TODO To be removed
  while (_sendData.try_lock() == FALSE) {
    // not ready yet
    std::this_thread::sleep_for(std::chrono::milliseconds(1));
  } // End of 'while' statement
garciay's avatar
garciay committed
512
  send_to_all_layers(data, params);
513
  _sendData.unlock();
514
  
garciay's avatar
garciay committed
515
  //loggers::get_instance().log("<<< geonetworking_layer::send_beacon");
516
517
} // End of send_beacon method

garciay's avatar
garciay committed
518
519
void geonetworking_layer::start_pass_beaconing(const LibItsGeoNetworking__TypesAndValues::BeaconHeader& p_beacon) {
  loggers::get_instance().log_msg(">>> geonetworking_layer::start_pass_beaconing", p_beacon);
520
521
522
523
524
525
526

  const LibItsGeoNetworking__TypesAndValues::LongPosVector& lpv = p_beacon.srcPosVector();
  if (!_pass_beacon_table.has_entry(lpv.gnAddr().mid())) {
    _pass_beacon_table.add_entry(lpv);
  } // TODO Refined adding a boolean return code
} // End of start_pass_beaconing method

garciay's avatar
garciay committed
527
528
void geonetworking_layer::stop_pass_beaconing() {
  loggers::get_instance().log(">>> geonetworking_layer::stop_pass_beaconing");
529
530
531
532

  _pass_beacon_table.reset();
} // End of stop_pass_beaconing method

garciay's avatar
garciay committed
533
534
int geonetworking_layer::enable_secured_mode(const std::string& p_certificate_id, const boolean p_enforce_security) {
  loggers::get_instance().log(">>> geonetworking_layer::enable_secured_mode: '%s' - %x", p_certificate_id.c_str(), p_enforce_security);
535

garciay's avatar
garciay committed
536
  loggers::get_instance().log("geonetworking_layer::enable_secured_mode: _secured_mode = %x", _secured_mode);
537
  if (!_secured_mode) {
garciay's avatar
garciay committed
538
    loggers::get_instance().log("geonetworking_layer::enable_secured_mode: Setup secured mode");
539
540
541
542
    _secured_mode = true;
    setup_secured_mode();
  }
  _enable_security_checks = p_enforce_security;
garciay's avatar
garciay committed
543
  params::const_iterator it = _params.find(params::certificate);
544
545
546
  if (it == _params.cend()) {
    _params.insert(std::pair<std::string, std::string>(std::string("certificate"), p_certificate_id));
  } else {
garciay's avatar
garciay committed
547
    _params[params::certificate] = p_certificate_id;
548
  }
garciay's avatar
garciay committed
549
  loggers::get_instance().log("geonetworking_layer::enable_secured_mode: Certificate to be used: '%s'", _params[params::certificate].c_str());
550
551
  
  return 0;
552
553
}

garciay's avatar
garciay committed
554
555
int geonetworking_layer::disable_secured_mode() {
  loggers::get_instance().log(">>> geonetworking_layer::disable_secured_mode");
garciay's avatar
garciay committed
556
557
558
559
560
  _secured_mode = false;
  _enable_security_checks = false;
  return 0;
}

garciay's avatar
garciay committed
561
const LongPosVector* geonetworking_layer::get_lpv(const GN__Address& p_gn_address)
562
{
garciay's avatar
garciay committed
563
  loggers::get_instance().log_msg(">>> geonetworking_layer::get_lpv", p_gn_address);
564
565
566
567
568
569
570
571
  
  const LongPosVector* lpv = nullptr;
  if (_location_table.has_entry(p_gn_address.mid())) {
    lpv = _location_table.get_entry(p_gn_address.mid());
  }
  return lpv;
} // End of get_lpv

572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
const LibItsGeoNetworking__TypesAndValues::BasicHeader geonetworking_layer::fill_basic_header() const {
  return LibItsGeoNetworking__TypesAndValues::BasicHeader(
                                                          1, // GeoNetworking version
                                                          BasicNextHeader(
                                                                          BasicNextHeader::e__commonHeader
                                                                          ),
                                                          0,
                                                          Lifetime(
                                                                   4,
                                                                   LtBase(LtBase::e__50ms)
                                                                   ),
                                                          1
                                                          );
}

garciay's avatar
garciay committed
587
void geonetworking_layer::fill_beacon(const OCTETSTRING& p_ll_address, const INTEGER p_station_type, const INTEGER p_country, const INTEGER type_of_address)
588
589
590
591
592
593
594
595
596
597
598
{
  _beacon = new GeoNetworkingPdu();
  HeaderTST h;
  h.beaconHdr() = BeaconHeaderType(
                                   HeaderType(HeaderType::e__beacon),
                                   0
                                   );
  ExtendedHeader eh;
  eh.beaconHeader() = BeaconHeader(
                                   LongPosVector(
                                                 GN__Address(
599
600
601
                                                             TypeOfAddress((TypeOfAddress)type_of_address),
                                                             StationType((StationType)p_station_type),
                                                             p_country,
602
603
604
                                                             p_ll_address
                                                             ),
                                                 0,
605
606
                                                 _latitude,
                                                 _longitude,
607
608
609
610
611
                                                 int2bit(0, 1),
                                                 0,
                                                 0
                                                 )
                                   );
612
  _beacon->basicHeader() = fill_basic_header();
613
614
615
616
617
618
619
620
  _beacon->gnPacket().packet() = GnNonSecuredPacket(
                                                    CommonHeader(
                                                                 NextHeader(
                                                                            NextHeader::e__any
                                                                            ),
                                                                 0,
                                                                 h,
                                                                 TrafficClass(
YannGarcia's avatar
YannGarcia committed
621
                                                                              SCF(SCF::e__scfEnabled),
622
623
624
625
626
627
628
629
630
631
632
633
634
                                                                              ChannelOffload(ChannelOffload::e__choffDisabled),
                                                                              0
                                                                              ),
                                                                 int2bit(0, 8),
                                                                 0,
                                                                 1,
                                                                 0
                                                                 ),
                                                    OPTIONAL<ExtendedHeader>(eh),
                                                    OPTIONAL<GnRawPayload>()
                                                    );
  _beacon->gnPacket().packet().payload().set_to_omit();
  _beacon->gnPacket().securedMsg().set_to_omit();
garciay's avatar
garciay committed
635
  //loggers::get_instance().log_msg("geonetworking_layer::fill_beacon: beacon value: ", *_beacon);
636
637
} // End of fill_beacon method
  
garciay's avatar
garciay committed
638
void geonetworking_layer::fill_gbc_packet(const OCTETSTRING& p_ll_address, const INTEGER& p_geoAreaPosLatitude, const INTEGER& p_geoAreaPosLongitude, const INTEGER& p_distanceA, const INTEGER& p_distanceB, const INTEGER& p_angle)
639
{
640
  _gbc_packet = new GeoNetworkingPdu();
641
642
643
644
645
646
647
648
649
650
651
  HeaderTST h;
  h.geoBroadcastHdr() = GeoBroadcastHeaderType(
                                               HeaderType(HeaderType::e__geoBroadcast),
                                               HeaderSubTypeGeoBroadcast(HeaderSubTypeGeoBroadcast::e__geoBroadcastElip)
                                               );
  ExtendedHeader eh;
  eh.geoBroadcastHeader() = GeoAnycastHeader( // GeoBradcastHeader is identical as GeoAnycastHeader
                                             0,
                                             0,
                                             LongPosVector(
                                                           GN__Address(
garciay's avatar
garciay committed
652
653
                                                                       TypeOfAddress(TypeOfAddress::e__manual), // TODO Use params
                                                                       StationType(StationType::e__passengerCar), // TODO Use params
654
655
656
657
                                                                       33,
                                                                       p_ll_address
                                                                       ),
                                                           0,
658
659
                                                           _latitude,
                                                           _longitude,
660
661
662
663
664
665
666
667
668
669
670
                                                           int2bit(1, 1), // PAI
                                                           0,
                                                           0
                                                           ),
                                             p_geoAreaPosLatitude,
                                             p_geoAreaPosLongitude,
                                             p_distanceA,
                                             p_distanceB,
                                             p_angle,
                                             0
                                              );
671
  _gbc_packet->basicHeader() = fill_basic_header();
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
  _gbc_packet->gnPacket().packet() = GnNonSecuredPacket(
                                                        CommonHeader(
                                                                     NextHeader(
                                                                                NextHeader::e__btpA
                                                                                ),
                                                                     0,
                                                                     h,
                                                                     TrafficClass(
                                                                                  SCF(SCF::e__scfDisabled),
                                                                                  ChannelOffload(ChannelOffload::e__choffDisabled),
                                                                                  0
                                                                                  ),
                                                                     int2bit(128, 8), // Mobile stationnary flag set
                                                                     0,
                                                                     5,
                                                                     0
                                                                     ),
                                                        OPTIONAL<ExtendedHeader>(eh),
                                                        OPTIONAL<GnRawPayload>()
                                                        );
  _gbc_packet->gnPacket().packet().payload().set_to_omit();
  _gbc_packet->gnPacket().securedMsg().set_to_omit();
garciay's avatar
garciay committed
694
  //loggers::get_instance().log_msg("geonetworking_layer::fill_gbc_packet: packet value: ", *_gbc_packet);
695
696
} // End of fill_gbc_packet method

garciay's avatar
garciay committed
697
void geonetworking_layer::fill_shb_packet(const OCTETSTRING& p_ll_address)
698
699
700
701
702
703
704
705
706
707
708
{
  _shb_packet = new GeoNetworkingPdu();
  HeaderTST h;
  h.tsbHdr() = TsbHeaderType(
                             HeaderType(HeaderType::e__topologicallyScopedBroadcast),
                             HeaderSubTypeTSB(HeaderSubTypeTSB::e__singleHop)
                             );
  ExtendedHeader eh;
  eh.shbHeader() = SHBHeader(
                             LongPosVector(
                                           GN__Address(
garciay's avatar
garciay committed
709
710
                                                       TypeOfAddress(TypeOfAddress::e__manual), // TODO Use params
                                                       StationType(StationType::e__passengerCar), // TODO Use params
711
712
                                                       33,
                                                       p_ll_address
713
                                                       ),
714
                                           0,
715
716
                                           _latitude,
                                           _longitude,
717
718
719
720
721
722
                                           int2bit(1, 1), // PAI
                                           0,
                                           0
                                           ),
                             0
                             );
723
  _shb_packet->basicHeader() = fill_basic_header();
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
  _shb_packet->gnPacket().packet() = GnNonSecuredPacket(
                                                        CommonHeader(
                                                                     NextHeader(
                                                                                NextHeader::e__btpA
                                                                                ),
                                                                     0,
                                                                     h,
                                                                     TrafficClass(
                                                                                  SCF(SCF::e__scfDisabled),
                                                                                  ChannelOffload(ChannelOffload::e__choffDisabled),
                                                                                  0
                                                                                  ),
                                                                     int2bit(128, 8), // Mobile stationnary flag set
                                                                     0,
                                                                     1,
                                                                     0
                                                                     ),
                                                        OPTIONAL<ExtendedHeader>(eh),
                                                        OPTIONAL<GnRawPayload>()
                                                        );
  _shb_packet->gnPacket().packet().payload().set_to_omit();
  _shb_packet->gnPacket().securedMsg().set_to_omit();
garciay's avatar
garciay committed
746
  //loggers::get_instance().log_msg("geonetworking_layer::fill_shb_packet: packet value: ", *_shb_packet);
747
748
} // End of fill_shb_packet method

garciay's avatar
garciay committed
749
void geonetworking_layer::fill_tsb_packet(const OCTETSTRING& p_ll_address, const int p_hop_number, const int p_max_hop_limit)
garciay's avatar
garciay committed
750
751
752
753
754
755
756
757
758
759
760
761
762
{
  _tsb_packet = new GeoNetworkingPdu();
  HeaderTST h;
  h.tsbHdr() = TsbHeaderType(
                             HeaderType(HeaderType::e__topologicallyScopedBroadcast),
                             HeaderSubTypeTSB(HeaderSubTypeTSB::e__multiHop)
                             );
  ExtendedHeader eh;
  eh.tsbHeader() = TSBHeader(
                             0,
                             0,
                             LongPosVector(
                                           GN__Address(
garciay's avatar
garciay committed
763
764
                                                       TypeOfAddress(TypeOfAddress::e__manual), // TODO Use params
                                                       StationType(StationType::e__passengerCar), // TODO Use params
garciay's avatar
garciay committed
765
766
767
768
                                                       33,
                                                       p_ll_address
                                                       ),
                                           0,
769
770
                                           _latitude,
                                           _longitude,
garciay's avatar
garciay committed
771
772
773
774
775
                                           int2bit(1, 1), // PAI
                                           0,
                                           0
                                           )
                             );
776
  _tsb_packet->basicHeader() = fill_basic_header();
garciay's avatar
garciay committed
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
  _tsb_packet->gnPacket().packet() = GnNonSecuredPacket(
                                                        CommonHeader(
                                                                     NextHeader(
                                                                                NextHeader::e__btpA
                                                                                ),
                                                                     0,
                                                                     h,
                                                                     TrafficClass(
                                                                                  SCF(SCF::e__scfDisabled),
                                                                                  ChannelOffload(ChannelOffload::e__choffDisabled),
                                                                                  0
                                                                                  ),
                                                                     int2bit(128, 8), // Mobile stationnary flag set
                                                                     0,
                                                                     p_max_hop_limit,
                                                                     0
                                                                     ),
                                                        OPTIONAL<ExtendedHeader>(eh),
                                                        OPTIONAL<GnRawPayload>()
                                                        );
  _tsb_packet->gnPacket().packet().payload().set_to_omit();
  _tsb_packet->gnPacket().securedMsg().set_to_omit();
garciay's avatar
garciay committed
799
  //loggers::get_instance().log_msg("geonetworking_layer::fill_tsb_packet: packet value: ", *_tsb_packet);
garciay's avatar
garciay committed
800
801
} // End of fill_tsb_packet method

Yann Garcia's avatar
Yann Garcia committed
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
void geonetworking_layer::fill_uni_packet(const OCTETSTRING& p_ll_address, const int p_hop_number, const int p_max_hop_limit)
{
  _uni_packet = new GeoNetworkingPdu();
  HeaderTST h;
  h.geoUnicastHdr() = GeoUnicastHeaderType(
                                           HeaderType(HeaderType::e__geoUnicast),
                                           0
                                           );
  ExtendedHeader eh;
  eh.geoUnicastHeader() = GeoUnicastHeader(
                                           0,
                                           0,
                                           LongPosVector(
                                                         GN__Address(
                                                                     TypeOfAddress(TypeOfAddress::e__manual), // TODO Use params
                                                                     StationType(StationType::e__passengerCar), // TODO Use params
                                                                     33,
                                                                     p_ll_address
                                                                     ),
                                                         0,
                                                         _latitude,
                                                         _longitude,
                                                         int2bit(1, 1), // PAI
                                                         0,
                                                         0
                                                         ),
                                           ShortPosVector(
                                                          GN__Address(
                                                                      TypeOfAddress(TypeOfAddress::e__manual), // TODO Use params
                                                                      StationType(StationType::e__passengerCar), // TODO Use params
                                                                      33,
                                                                      p_ll_address
                                                                      ),
                                                          0,
                                                          _latitude + 100,
                                                          _longitude + 100
                                                   )
                             );
  _uni_packet->basicHeader() = fill_basic_header();
  _uni_packet->gnPacket().packet() = GnNonSecuredPacket(
                                                        CommonHeader(
                                                                     NextHeader(
                                                                                NextHeader::e__btpA
                                                                                ),
                                                                     0,
                                                                     h,
                                                                     TrafficClass(
                                                                                  SCF(SCF::e__scfDisabled),
                                                                                  ChannelOffload(ChannelOffload::e__choffDisabled),
                                                                                  0
                                                                                  ),
                                                                     int2bit(128, 8), // Mobile stationnary flag set
                                                                     0,
                                                                     p_max_hop_limit,
                                                                     0
                                                                     ),
                                                        OPTIONAL<ExtendedHeader>(eh),
                                                        OPTIONAL<GnRawPayload>()
                                                        );
  _uni_packet->gnPacket().packet().payload().set_to_omit();
  _uni_packet->gnPacket().securedMsg().set_to_omit();
  //loggers::get_instance().log_msg("geonetworking_layer::fill_uni_packet: packet value: ", *_uni_packet);
} // End of fill_uni_packet method

garciay's avatar
garciay committed
866
void geonetworking_layer::fill_ls_reply(const OCTETSTRING& p_ll_address)
867
868
869
870
871
872
873
874
875
876
877
878
879
{
  _ls_reply = new GeoNetworkingPdu();
  HeaderTST h;
  h.lsHdr() = LsHeaderType(
                           HeaderType(HeaderType::e__locationService),
                           HeaderSubTypeLs(HeaderSubTypeLs::e__lsReply)
                           );
  ExtendedHeader eh;
  eh.lsReplyHeader() = LSReplyHeader(
                                     0,
                                     0,
                                     LongPosVector(
                                                   GN__Address(
garciay's avatar
garciay committed
880
881
                                                               TypeOfAddress(TypeOfAddress::e__manual), // TODO Use params
                                                               StationType(StationType::e__passengerCar), // TODO Use params
882
883
884
885
                                                               33,
                                                               p_ll_address
                                                               ),
                                                   0,
886
887
                                                   _latitude,
                                                   _longitude,
888
889
890
891
892
893
                                                   int2bit(1, 1), // PAI
                                                   0,
                                                   0
                                                   ),
                                     ShortPosVector(
                                                    GN__Address(
garciay's avatar
garciay committed
894
895
                                                                TypeOfAddress(TypeOfAddress::e__manual), // TODO Use params
                                                                StationType(StationType::e__passengerCar), // TODO Use params
896
897
898
899
                                                                33,
                                                                p_ll_address
                                                                ),
                                                    0,
900
901
                                                    _latitude,
                                                    _longitude
902
903
                                                    )
                                     );
904
  _ls_reply->basicHeader() = fill_basic_header();
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
  _ls_reply->gnPacket().packet() = GnNonSecuredPacket(
                                                      CommonHeader(
                                                                   NextHeader(
                                                                              NextHeader::e__any
                                                                              ),
                                                                   0,
                                                                   h,
                                                                   TrafficClass(
                                                                                SCF(SCF::e__scfDisabled),
                                                                                ChannelOffload(ChannelOffload::e__choffDisabled),
                                                                                0
                                                                                ),
                                                                   int2bit(128, 8), // Mobile stationnary flag set
                                                                   0,
                                                                   5,
                                                                   0
                                                                   ),
                                                      OPTIONAL<ExtendedHeader>(eh),
                                                      OPTIONAL<GnRawPayload>()
                                                      );
  _ls_reply->gnPacket().packet().payload().set_to_omit();
  _ls_reply->gnPacket().securedMsg().set_to_omit();
garciay's avatar
garciay committed
927
  //loggers::get_instance().log_msg("geonetworking_layer::fill_ls_reply: packet value: ", *_ls_reply);
928
} // End of fill_ls_reply method
929

garciay's avatar
garciay committed
930
931
void geonetworking_layer::timer_irq_sigalrm_handler(int p_signal, siginfo_t *p_signal_info, void *p_uc) {
  //loggers::get_instance().log(">>> geonetworking_layer::timer_irq_sigalrm_handler: Caught signal %d", p_signal);
932

garciay's avatar
garciay committed
933
  static_cast<geonetworking_layer *>(p_signal_info->si_value.sival_ptr)->send_beacon();
934
935
} // End of method timer_irq_sigalrm_handler

garciay's avatar
garciay committed
936
int geonetworking_layer::build_geonetworking_pdu(OCTETSTRING& data, params& params) {
garciay's avatar
garciay committed
937
  loggers::get_instance().log(">>> geonetworking_layer::build_geonetworking_pdu");
garciay's avatar
garciay committed
938
  //params.log();
939
940
  
  std::string next_header;
garciay's avatar
garciay committed
941
  params::const_iterator it = params.find(params::next_header);
942
943
944
945
  if (it != params.cend()) {
    next_header = it->second.c_str();
  }
  std::string header_type;
garciay's avatar
garciay committed
946
  it = params.find(params::header_type);
947
948
949
950
  if (it != params.cend()) {
    header_type = it->second.c_str();
  }
  std::string header_sub_type;
garciay's avatar
garciay committed
951
  it = params.find(params::header_sub_type);
952
953
954
  if (it != params.cend()) {
    header_sub_type = it->second.c_str();
  }
garciay's avatar
garciay committed
955
  loggers::get_instance().log("geonetworking_layer::build_geonetworking_pdu: %s, %s, %s", next_header.c_str(), header_type.c_str(), header_sub_type.c_str());
956
957
958
959
960
  
  if (header_type.compare("tsb") == 0) {
    if (header_sub_type.compare("sh") == 0) { // Use SHB
      ExtendedHeader* eh = static_cast<ExtendedHeader *>(_shb_packet->gnPacket().packet().extendedHeader().get_opt_value());
      if (eh == nullptr) {
garciay's avatar
garciay committed
961
        loggers::get_instance().error("geonetworking_layer::build_geonetworking_pdu: Wrong cast");
962
963
964
        return -1;
      }
      // Update NextHeader
garciay's avatar
garciay committed
965
      it = params.find(params::next_header);
966
967
968
969
970
971
972
973
974
      if (next_header.compare("btpB") == 0) {
        _shb_packet->gnPacket().packet().commonHeader().nextHeader() = NextHeader::e__btpB;
      } else { // Default btp is btpA
        _shb_packet->gnPacket().packet().commonHeader().nextHeader() = NextHeader::e__btpA;
      }
      // Update payload
      _shb_packet->gnPacket().packet().commonHeader().plLength() = data.lengthof();
      _shb_packet->gnPacket().packet().payload() = OPTIONAL<OCTETSTRING>(data);
      // Update timestamp
Yann Garcia's avatar
Yann Garcia committed
975
      eh->shbHeader().srcPosVector().timestamp__().set_long_long_val(static_cast<unsigned int>(base_time::get_instance().get_its_current_time_mod_ms()));
976
      
garciay's avatar
garciay committed
977
      loggers::get_instance().log_msg("geonetworking_layer::build_geonetworking_pdu: shb: ", *_shb_packet);
978
979
980
981
      // Encode GeoNetworking PDU
      OCTETSTRING os;
      _codec.encode(*_shb_packet, os);
      data = os;
garciay's avatar
garciay committed
982
983
984
    } else { // Use TSB
      ExtendedHeader* eh = static_cast<ExtendedHeader *>(_tsb_packet->gnPacket().packet().extendedHeader().get_opt_value());
      if (eh == nullptr) {
garciay's avatar
garciay committed
985
        loggers::get_instance().error("geonetworking_layer::build_geonetworking_pdu: Wrong cast");
garciay's avatar
garciay committed
986
987
988
989
990
        return -1;
      }
      // Update sequence number
      eh->tsbHeader().seqNumber() = _sequence_number++;
      // Update NextHeader
garciay's avatar
garciay committed
991
      it = params.find(params::next_header);