GeoNetworkingLayer.cc 9.31 KB
Newer Older
garciay's avatar
garciay committed
1
2
#include <chrono>

garciay's avatar
garciay committed
3
4
5
6
7
#include "GeoNetworkingLayer.hh"
#include "GeoNetworkingTypes.hh"

#include "loggers.hh"

garciay's avatar
garciay committed
8
9
using namespace LibItsGeoNetworking__TypesAndValues;

10
GeoNetworkingLayer::GeoNetworkingLayer(const std::string & p_type, const std::string & param) : TLayer<LibItsGeoNetworking__TestSystem::GeoNetworkingPort>(p_type), _params(), _codec(), _beacon(NULL), _thread(NULL), _sendData(), _running(FALSE) {
garciay's avatar
garciay committed
11
  loggers::get_instance().log(">>> GeoNetworkingLayer::GeoNetworkingLayer: %s, %s", to_string().c_str(), param.c_str());
garciay's avatar
garciay committed
12
13
  // Setup parameters
  Params::convert(_params, param);
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
  // Sanity checks
  INTEGER latitude;
  Params::const_iterator it = _params.find(Params::latitude);
  if (it != _params.cend()) {
    latitude = str2int(CHARSTRING(it->second.c_str()));
  }
  INTEGER longitude;
  it = _params.find(Params::longitude);
  if (it != _params.cend()) {
    longitude = str2int(CHARSTRING(it->second.c_str()));
  }
  OCTETSTRING ll_address;
  it = _params.find(Params::ll_address);
  if (it != _params.cend()) {
    ll_address = str2oct(CHARSTRING(it->second.c_str()));
  }
  // Add broadcast address if needed
  it = _params.find("mac_bc");
garciay's avatar
garciay committed
32
33
34
  if (it == _params.cend()) {
    _params.insert(std::pair<std::string, std::string>(std::string("mac_bc"), "FFFFFFFFFFFF"));
  }
35
  fill_beacon(latitude, longitude, ll_address);
garciay's avatar
garciay committed
36
  // Prepare the static part of the TestSystem beacon
37
38
39
40
  it = _params.find("");
  if ((it != _params.cend()) && (it->second.compare("1") == 0)) {
    start_beaconing();
  }
41
42
}

garciay's avatar
garciay committed
43
GeoNetworkingLayer::~GeoNetworkingLayer() {
garciay's avatar
garciay committed
44
45
  stop_beaconing();
  delete _beacon;
garciay's avatar
garciay committed
46
47
}
void GeoNetworkingLayer::sendMsg(const LibItsGeoNetworking__TestSystem::GeoNetworkingReq& p, Params& params) {
garciay's avatar
garciay committed
48
  loggers::get_instance().log(">>> GeoNetworkingLayer::sendMsg");
garciay's avatar
garciay committed
49
50

  // Encode GeoNetworking PDU
garciay's avatar
garciay committed
51
52
  OCTETSTRING data;
  _codec.encode(p.msgOut(), data);
garciay's avatar
garciay committed
53
  sendData(data, params);
garciay's avatar
garciay committed
54
55
}

garciay's avatar
garciay committed
56
void GeoNetworkingLayer::sendData(OCTETSTRING& data, Params& params) {
garciay's avatar
garciay committed
57
  loggers::get_instance().log_msg(">>> GeoNetworkingLayer::sendData: ", data);
58
59
60
61
  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
62
  sendToAllLayers(data, params);
63
64
  _sendData.unlock();
  loggers::get_instance().log("<<< GeoNetworkingLayer::sendData");
garciay's avatar
garciay committed
65
66
}

garciay's avatar
garciay committed
67
void GeoNetworkingLayer::receiveData(OCTETSTRING& data, Params& params) { 
garciay's avatar
garciay committed
68
  loggers::get_instance().log_msg(">>> GeoNetworkingLayer::receiveData: ", data);
garciay's avatar
garciay committed
69
70
  // Decode the payload
  LibItsGeoNetworking__TestSystem::GeoNetworkingInd p;
71
  _codec.decode(data, p.msgIn(), &params);
garciay's avatar
garciay committed
72
  // Add lower layers parameters
garciay's avatar
garciay committed
73
  // 1. Destination MAC address
garciay's avatar
garciay committed
74
  Params::const_iterator it = params.find(Params::mac_dst);
garciay's avatar
garciay committed
75
  if (it != params.cend()) {
76
    loggers::get_instance().log("GeoNetworkingLayer::receiveData: dst=%s", it->second.c_str());
garciay's avatar
garciay committed
77
78
    p.macDestinationAddress() = str2oct(CHARSTRING(it->second.c_str()));
  } else {
garciay's avatar
garciay committed
79
    p.macDestinationAddress() = str2oct(CHARSTRING(_params["mac_bc"].c_str()));
garciay's avatar
garciay committed
80
81
82
83
  }
  // 2. ssp
  it = params.find(Params::ssp);
  if (it != params.cend()) {
84
    loggers::get_instance().log("GeoNetworkingLayer::receiveData: ssp=%s", it->second.c_str());
garciay's avatar
garciay committed
85
86
87
    p.ssp() = str2bit(CHARSTRING(it->second.c_str()));
  } else {
    p.ssp().set_to_omit();
garciay's avatar
garciay committed
88
  }
garciay's avatar
garciay committed
89
90
91
  // 3. its_aid
  it = params.find(Params::its_aid);
  if (it != params.cend()) {
92
    loggers::get_instance().log("GeoNetworkingLayer::receiveData: its_aid=%s", it->second.c_str());
garciay's avatar
garciay committed
93
94
95
96
97
    p.its__aid() = std::stoi(it->second.c_str());
  } else {
    p.its__aid().set_to_omit();
  }
  
98
99
100
101
102
103
104
105
106
107
  // Pass the GeoNetworking raw payload to the upper layers if any
  it = params.find(Params::gn_payload);
  if (it != params.cend()) {
    loggers::get_instance().log("GeoNetworkingLayer::receiveData: gn_payload=%s", it->second.c_str());
    OCTETSTRING os(str2oct(CHARSTRING(it->second.c_str())));
    receiveToAllLayers(os, params);
  } else {
    loggers::get_instance().warning("GeoNetworkingLayer::receiveData: No payload to pass to upper layers");
  }
  // Pass it to the ports
garciay's avatar
garciay committed
108
  toAllUpperPorts(p, params);
garciay's avatar
garciay committed
109
110
}

garciay's avatar
garciay committed
111
void GeoNetworkingLayer::start_beaconing() {
garciay's avatar
garciay committed
112
113
  loggers::get_instance().log(">>> GeoNetworkingLayer::start_beaconing");

114
115
116
117
118
  // Sanity checks
  if (_thread != NULL) { // Already started
    return;
  }

garciay's avatar
garciay committed
119
120
121
122
123
124
125
126
127
128
129
  // Create the offline reader thread
  _thread = new std::thread(&GeoNetworkingLayer::run_beaconing, (void *)this);
  if (_thread == NULL) {
    loggers::get_instance().error("GeoNetworkingLayer::start_beaconing: Failed to start beaconing thread");
  }
  // Wait for the thread
  while (_running == FALSE) {
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
  }
  // Thread was started
  loggers::get_instance().log("<<< PcapLayer::PcapLayer");    
garciay's avatar
garciay committed
130
131
132
133
134
135
136
137
138
139
140
141
142
}

void GeoNetworkingLayer::stop_beaconing() {
  loggers::get_instance().log(">>> GeoNetworkingLayer::stop_beaconing");
  if (_thread != NULL) {
    _running = FALSE;
    // Wait for the working thread to terminate
    _thread->join();
    loggers::get_instance().log("GeoNetworkingLayer::stop_beaconing: Thread were stops");
    _thread = NULL;
  }
}

garciay's avatar
garciay committed
143
144
145
146
147
148
void* GeoNetworkingLayer::run_beaconing(void* p_this) {
  loggers::get_instance().log(">>> GeoNetworkingLayer::run_beaconing");

  // Pointer the main object
  GeoNetworkingLayer& p = *static_cast<GeoNetworkingLayer *>(p_this);
  Params params(p._params);
149
  std::chrono::milliseconds expiry(1000); // Default is set to 1 second
garciay's avatar
garciay committed
150
151
  Params::const_iterator it = params.find("TsBeaconInterval");
  if (it != params.cend()) {
152
    expiry = std::chrono::milliseconds(std::stoul(it->second));
garciay's avatar
garciay committed
153
154
155
156
157
158
  }
  ExtendedHeader* eh = static_cast<ExtendedHeader *>(p._beacon->gnPacket().packet().extendedHeader().get_opt_value());
  if (eh == NULL) {
    loggers::get_instance().error("GeoNetworkingLayer::run_beaconing: Wrong cast");
  }
  GeoNetworkingCodec codec;
159
  // Start beaconing
garciay's avatar
garciay committed
160
  p._running = TRUE;
161
162
  std::this_thread::sleep_for(std::chrono::milliseconds(100));
  while (p._running == TRUE) { // Loop while _running flag is up
garciay's avatar
garciay committed
163
    // Update timestamp
164
    unsigned long long ms = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count() - 1072911600000L; // TODO Add method such as its_tme() & its_time_mod()
garciay's avatar
garciay committed
165
    eh->beaconHeader().srcPosVector().timestamp__() = ms;
166
167
168
169
    // Encode message using TITAN because of payload in omited
    TTCN_Buffer encoding_buffer;
    p._beacon->encode(*(p._beacon->get_descriptor()), encoding_buffer, TTCN_EncDec::CT_RAW);
    OCTETSTRING data(encoding_buffer.get_len(), encoding_buffer.get_data());
garciay's avatar
garciay committed
170
171
172
    // Send it
    p.sendData(data, params);
    // Timer
173
174
175
    ms = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count() + expiry.count();
    while ((p._running == TRUE) && (ms > std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count()));
  } // End of 'while' statement<
garciay's avatar
garciay committed
176
177
178
179
180
  
  loggers::get_instance().log("<<< GeoNetworkingLayer::run_beaconing");
  return NULL;
}

181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
void GeoNetworkingLayer::fill_beacon(INTEGER& p_latitude, INTEGER& p_longitude, OCTETSTRING& p_ll_address)
{
  _beacon = new GeoNetworkingPdu();
  HeaderTST h;
  h.beaconHdr() = BeaconHeaderType(
				   HeaderType(HeaderType::e__beacon),
				   0
				   );
  ExtendedHeader eh;
  eh.beaconHeader() = BeaconHeader(
				   LongPosVector(
						 GN__Address(
							     TypeOfAddress(TypeOfAddress::e__manual),
							     StationType(StationType::e__roadSideUnit),
							     33,
							     p_ll_address
							     ),
						 0,
						 p_latitude,
						 p_longitude,
						 int2bit(0, 1),
						 0,
						 0
						 )
				   );
  _beacon->basicHeader() = BasicHeader(
				       0,
				       BasicNextHeader(
						       BasicNextHeader::e__commonHeader
						       ),
				       0,
				       Lifetime(
						4,
						LtBase(LtBase::e__50ms)
						),
				       5
				       );
  _beacon->gnPacket().packet() = GnNonSecuredPacket(
						    CommonHeader(
								 NextHeader(
									    NextHeader::e__any
									    ),
								 0,
								 h,
								 TrafficClass(
									      SCF(SCF::e__scfDisabled),
									      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();
  //  loggers::get_instance().log_msg("GeoNetworkingLayer::GeoNetworkingLayer: beacon value: ", *p._beacon);
}

garciay's avatar
garciay committed
243
class GeoNetworkingFactory: public LayerFactory {
garciay's avatar
garciay committed
244
  static GeoNetworkingFactory _f;
garciay's avatar
garciay committed
245
public:
garciay's avatar
garciay committed
246
247
248
  GeoNetworkingFactory();
  virtual Layer * createLayer(const std::string & type,
			      const std::string & param);
garciay's avatar
garciay committed
249
250
251
};

GeoNetworkingFactory::GeoNetworkingFactory() {
garciay's avatar
garciay committed
252
253
254
  // Register factory
  loggers::get_instance().log(">>> GeoNetworkingFactory::GeoNetworkingFactory");
  LayerStackBuilder::RegisterLayerFactory("GN", this);
garciay's avatar
garciay committed
255
256
257
}

Layer * GeoNetworkingFactory::createLayer(const std::string & type, const std::string & param) {
garciay's avatar
garciay committed
258
  return new GeoNetworkingLayer(type, param);
garciay's avatar
garciay committed
259
260
261
}

GeoNetworkingFactory GeoNetworkingFactory::_f;